I am a scala beginner and I face a problem when I am doing my homework because there is null in the text file for example (AFG,Asia,Afghanistan,2020-02-24,1.0,1.0,,,,,0.026,0.026). So, I need to replace the null in array with zero. I read the scala array members and try the update and filter method but I cannot solve it. Can someone help me?
val filename = "relevant.txt" //Access File
val rf = Source.fromFile(filename).getLines.toArray //Read File as Array
for(line <- rf){ //for loop
line.(**How to replace the null with 0?**)
//println(line.split(",")(0))
if (line.split(",")(0).trim().equalsIgnoreCase(iso_code)){ //check for correct ISO CODE , ignores the casing of the input
total_deaths += line.split(",")(4).trim().toDouble //increases based on the respective array position
sum_of_new_deaths += line.split(",")(5).trim().toDouble
record_count += 1 //increment for each entry
}
}
val cells = line.split(",")
.map(_.trim)
.map(it => if (it.isEmpty) "0" else it)
Then you can use it like total_deaths += cells(4).toDouble
BTW, null usually refers to "null pointer" in scala.
In your case, you don't have any "null pointer", you just have "empty string"
What you may do is something like this:
for (line <- rf) {
val data = line.split(',').toList.map(str => Option(str).filter(_.nonEmpty))
}
That way data would be a List[Option[String]] where empty values will be None, then you may use pattern matching to extra the data you want.
if you had to apply the change where you want:
//line.(**How to replace the null with 0?**)
you could do:
val line2 = if (line.trim().isEmpty) "," else line
then use line2 everywhere else.
As a side thing, if you want to do something more scala, replace .toArray with .toList and have a look at how map, filter, sum etc work.
Related
this is my first question so i hope I am doiung the tagging and so on right.
I have an array of objects of the same class. When I want to access a property of the objects I can use:
Data = [ObjectArray.property];
Now I want to call a mehtod of the class for each object and get back the result as Vektor/ matrice:
result = [ObjectArray.myfun(X)]
here I get an error saying:
Expected one output from curly brace or dot indexing expression
I tried brute force several different annotation but nothing works and i can't find a solution online.
Anybody knows how to make this work?
Thanks and Cheers!
It's slightly unclear what the structure of your array is, but you should be able to use arrayfun.
result = arrayfun( #(obj) obj.myfun(x), ObjectArray );
If you function myfun returns anything other than a scalar, you will need to set the UniformOutput flag to be false. This will make the result a cell array, with one cell per result.
result = arrayfun( #(obj) obj.myfun(x), ObjectArray, 'uni', false );
% If you want to concatenate results, could use something like
% result = [result{:}];
Note that this is basically shorthand for a loop, but it saves you pre-allocating an output and writing the loop.
You can also do this directly inside of your myfun:
If the item you operate your method on is an array, the first parameter of your myfun method will be an array. This can be used, and call itself one by one:
vec = [MyClass(1), MyClass(2)];
list = vec.myfun();
classdef MyClass
properties
prop1
end
methods
function obj = MyClass(val)
obj.prop1 = val;
end
function val = myfun(obj)
if numel(obj) > 1
val = arrayfun(#(o) o.myfun(), obj);
return;
end
val = obj.prop1;
end
end
end
I have the 1x1008 struct array EEG.event with fields
latency
duration
channel
bvtime
bvmknum
type
code
urevent
I want to delete all rows where entry in field EEG.event.type = 'boundary' or 'R 1'
I tried the following loop:
for b = 1:length(EEG.event)
if strcmp(EEG.event(b).type, 'boundary')
EEG.event(b) = [];
elseif strcmp(EEG.event(b).type, 'R 1')
EEG.event(b) = [];
end
end
This does not work of course, since the counting variable b at some point exceeds the length of EEG.event.
Does anyone have an idea how to delete particular rows?
The fundamental issue that you are having is that you are modifying the same array of structs that you are trying to loop through. This is generally a bad idea and will lead to the issue that you are seeing.
The easiest way to do this is to actually convert the event.type fields of all structs to a cell array, and use strcmp on all of them simultaneously to construct a logical matrix that you can use to index into EEG.event to get the entries you care about.
You can put all of the type values in a cell array like this
types = {EEG.event.type};
Then create your logical array by looking for event types of 'boundary'
isBoundary = strcmp(types, 'boundary');
And get the subset of EEG.event entries like this.
boundaryEvents = EEG.event(isBoundary);
If you want a subset of your events where the type isn't 'boundary' or 'R 1', then you can get that subset this way.
isBoundary = strcmp(types, 'boundary');
isR1 = strcmp(types, 'R 1');
% Keep the entries that aren't boundary or R1 types
events_to_use = EEG.event(~(isBoundary | isR1));
Change your loop to iterate backward through the array, deleting elements toward the end first:
for b = length(EEG.event):-1:1
...
Thanks all for your answers!
This straight forward line of code does the job:
[ EEG.event( strcmp( 'boundary', { EEG.event.type } ) | strcmp( 'R 1', { EEG.event.type } ) ) ] = [];
Cheers!
I want to create a function that encrypts the input sentence. This encryption will replace the first letter of each word with the next letter in the ASCII table, and the second letter with the next, ....
So basically, the resulting output for abc def should be bcd efg. However, when I run my function, the space will also be replaced, i.e. output will be bcd!efg. Why is this so? Thanks.
Below is what I have written:
function out = encrypt(input)
ascii_encode=double(input);
line={ascii_encode};
counter=0;
for a=1:length(line)
if line{a}==32
counter=0;
else
counter=counter+1;
line{a}=line{a}+counter;
end
line{a}=char(line{a});
end
out=line;
end
You should be careful handling cells.
Try line{a} , line(a) , line(1){a}, to understand how they work.
The code should be like this,
function out = encrypt(input)
ascii_encode = double(input);
line = {ascii_encode};
for a = 1 : length(line{1})
if line{1}(a) == 32
continue;
end
line{1}(a) = line{1}(a) + 1;
end
line{1} = char(line{1});
out = line{1};
end
And there is no need for counter, you just have to jump when if is true.
Kamtal's answer is perfectly right. You assign your input to a cell and then you were not accessing an index in the cell value (which is still a char array), but the full cell value.
Follow Kamtal answer if you still want to use cells type, and look at the cell documentation.
Note that you could also benefit by Matlab vectorization capabilities, and simplify your function by:
function out = encrypt(input)
charToKeep = ( input==' ' ) ; %// save position of character to keep
out = char(input+1) ; %// apply the modification on the full string
out(charToKeep) = ' ' ; %// replace the character we saved in their initial position
end
i have a problem with VBScript.
I am trying to loop through an array to compare all the values match.
I.e i have a tring array like the one below. i want to compare each of the values match using vbscript.
tmp(0) = "12345"
tmp(1) = "12345"
tmp(2) = "12345"
tmp(3) = "12345"
tmp(4) = "12345"
If i loop over the array i will have to do this twice in order to compare the vals. But how can i handle the first values. If the first value is wrong then its never picked up as both arrays are identical. I do not know how to get around this problem. Could someone please advise.
for x=0 to UBound(tmp)
for each val in tmp
if ( tmp(x) <> val)
print (mismatch)
End if
Next
Next
Not sure if I understand your question correctly. Do you want to check if all values of an array are equal? If so, something like this should do:
elementsEqual = True
For i = 1 To UBound(tmp)
If tmp(i) <> tmp(0) Then
elementsEqual = False
Exit For
End If
Next
You don't need to compare each element with each other element to check if all are equal. If not all elements are equal, then one of them will be inequal to the first element, so you just need a single loop.
I've got a .txt file set up in the following format:
7
8
9
10
What I'm trying to do, is read in the numbers from the file into an array and then check if a number I'm getting from a different function is contained within that array.
ismember(ruleFunc{x+1},memFunc}
I'm pretty sure that will check if the element from ruleFunc is in the array memFunc and return 1/0 if it is or isn't. But I can't get the ismember function to work properly because the method I'm using to populate the memFunc array is wrong.
Additionally, how am I able to add another number to the .txt file on a new line?
EDIT:
Here is how I am populating memFunc currently. It's also the same method that populates ruleFunc.
mem=fopen('WorkingMemory.txt');
tline = fgets(mem);
workMem = {};
index = 1;
while ischar(tline)
workMem{index} = str2num(tline);
tline = fgets(mem);
index = index + 1;
end
The function ismember returns a matrix that is 1 where the inputs are equal. (See the documenation for more information.) You might actually want something that returns a number, 1 or 0, depending on weather or not your number is in the matrix at all. I've included both options below.
% read in file
filename = 'my_data.txt';
fid = fopen(filename);
data = textscan(fid, '%d');
data = data{1};
fclose(fid);
% determine if number is in the file
number = 33;
ismember(data,number) %this returns an array
length(find(data == number)) > 0 % this returns 1 or 0
%write a line to existing file
fid2 = fopen(filename,'a');
newnumber = 100;
fprintf(fid2, '%d\n', newnumber);
fclose(fid2);
Now I see your updated answer. That code will read each line into a different cell of a cell array. You want all your data in a matrix. You could rearrange your cell array and put the data into a matrix or you could use textscan as described above.
In response to your comment, you can make an if statement like this:
if (length(find(data == number)) > 0)
'do something'
end
Maybe you are actually creating an array containing strings instead of numbers?
If it's not as simple as that, more information / code snippets would be useful. You mention the method populating memFunc may be wrong, maybe you could post that code?