Scala Collections - Making a new array from an existing using certain rules - arrays

I'm trying to make a function in Scala that when -
println(thisIsAFunction(Array(1,1,4,5,4,4)))
is called, it will give me a new array that is always half the size of the array input (the array input will always be an even number and bigger than 2), and in the new array it will not contain the same number twice. So for example, in the above statement, it would return an array consisting of the numbers 1, 4 and 5. I have been trying to approach this a number of ways but can't get my head round it.

def thisIsAFunction(a: Array[Int]) =
a.distinct.take(a.length/2)
The distinct method removes any duplicates from the Array so that it does not contain the same number twice.
The take methods reads the first n elements of the result, so take(a.length/2) gives an Array that is half the length of the original.

Related

Sort array based on last digit (as array values are seprated by _ )

my array have is
let arr=['20336.41905.32121.58472_20336.41905.60400.51092_1',
'20336.41905.32121.58472_20336.41905.60400.48025_2',
'20336.41905.32121.58472_20336.41905.41816.60719_3',
'20336.41905.32121.58472_20336.41905.41816.63631_4',
'20336.41905.32121.58472_20336.41905.31747.22942_2',
]
want to get sort as an order like this
['20336.41905.32121.58472_20336.41905.60400.51092_1',
'20336.41905.32121.58472_20336.41905.60400.48025_2',
'20336.41905.32121.58472_20336.41905.31747.22942_2',
'20336.41905.32121.58472_20336.41905.41816.60719_3',
'20336.41905.32121.58472_20336.41905.41816.63631_4',
]
We can try sorting using a lambda expression:
var arr = ['20336.41905.32121.58472_20336.41905.60400.51092_1',
'20336.41905.32121.58472_20336.41905.60400.48025_2',
'20336.41905.32121.58472_20336.41905.41816.60719_3',
'20336.41905.32121.58472_20336.41905.41816.63631_4',
'20336.41905.32121.58472_20336.41905.31747.22942_2',
];
arr.sort((a, b) => parseInt(a.split(/_(?!.*_)/)[1]) - parseInt(b.split(/_(?!.*_)/)[1]));
console.log(arr);
The logic used above is to split on the final underscore of each array value, and parse the right side number to an integer. Then we do a comparison of each pair of numbers to achieve the sort.
Assuming you are using JavaScript...
The sort function can take a callback as an argument. You can use this to determine the criteria by which you desire to sort your array.
When comparing 2 values compare a to b, the function should return a number greater than zero if a goes after b, less than zero if a goes before b, and exactly zero if any could follow the other (ie. 1.10 and 1.100 could be sorted as [1.10, 1.00] or [1.100, 1.00] because for all we care they have the same value, on your particular case, 2 array elements ending in 4 would follow the same principle because that is the only number in our criteria).
An example would be:
arr.sort((a, b)=>{
return parseInt(a.slice(-1)) - parseInt(b.slice(-1))
})
Note that this will only work if the last character on every element of your array is a numeric character and would not ever care about the second to last character if 2 last characters are equal.
There is an ugliest solution too that could work, although I don't really recommend it, it would take into consideration all characters in reverse order.
Map over all elements, reverse them, sort the array without using a callback (arr.sort()), and then reverse all elements again.

Match each element of one array with elements of other array without loops

I want to match each element of one array (lessnum) with elements of the other array say (cc). Then multiply with a number from the third array (gl). I am doing using loops. The length of arrays are very large therefore it takes couple of hours. Is it possible to do without loops or make it faster. Here is the code, I am doing,
uniquec=sort(unique(cc));
maxc=max(uniquec);
c35p=0.35*maxc;
lessnum=uniquec(uniquec<=c35p);
greaternum=uniquec(uniquec>c35p);
gl=linspace(1,2,length(lessnum));
gr=linspace(2,1,length(greaternum));
newC=zeros(size(cc));
for i=1:length(gl)
newC(cc==lessnum(i))= cc(cc==lessnum(i)).*gl(i);
end
for i=1:length(gr)
newC(cc==greaternum(i))= cc(cc==greaternum(i)).*gr(i);
end
What you need to do is instead of storing the values that are less than or greater than c35p in lessnum and greaternum, respectively, you should store the indices of these numbers. That way, you can directly access the newC variable using these indices and then multiply your linearly generated values.
Further modifications are explained in the code itself. If you have any confusion you can read the help for unique
Here is the modified code (I assume that cc is a one-dimensional array)
%randomly generate a cc vector
cc = randi(100, 1, 10);
% modified code below
[uniquec, ~, induniquec]=unique(cc, 'sorted'); % modified to explicitly specify the inbuilt sorting capability of unique and generate the indicies of unique values in the array
maxc=max(uniquec);
c35p=0.35*maxc;
lessnum=uniquec<=c35p; % instead of lessnum=uniquec(uniquec<=c35p);
greaternum=uniquec>c35p; % instead of greaternum=uniquec(uniquec>c35p);
gl=linspace(1,2,sum(lessnum));
gr=linspace(2,1,sum(greaternum));
% now there is no need for 'for' loops. We first modify the unique values as specified and then regenerate the required matrix using the indices obtained previously
newC=uniquec;
newC(lessnum) = newC(lessnum) .* gl;
newC(greaternum) = newC(greaternum) .* gr;
newC = newC(induniquec);
This new code will run much faster than the original one but is much more memory intensive depending on the number of unique values in your original array.

MATLAB: use strcmp(s1,s2) for variable length vector with strings

I have a query which I am trying to solve
I know that one can use strcmp(s1,s2) to compare two different strings to see whether they are the same. It gives 1 if that is the case.
However, how would one tackle this problem if you have a variable length array full of strings and you want to the whether all strings in the array are the same.
For example: ['NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'] we can see that all the strings are the same in this array. However, how would one go about with using strcmp(s1,s2).
Thanks guys!
If you want all pairwise comparisons between strings: call ndgrid to generate indices of all combinations, and then index into your cell array of strings and call strcmp:
x = {'NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'};
[ii, jj] = ndgrid(1:numel(x));
result = strcmp(x(ii), x(jj));
In this case
result =
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
because all strings are the same.
You probably had a pairwise comparison using strcmp in mind, but you can use it directly on cell arrays:
x={'NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'}
result=all(strcmpi(x{1},x(2:end)))
Compare the first element to the remaining elements. It returns true only if all elements are equal. For a pairwise comparison you could us:
[~,~,c]=unique(x);
result=bsxfun(#eq,c,c.')
If you're solving the problem with a matrix (i.e. every row is a string) there are no particularly nice solutions in my opinion, but if your strings are contained into a cell array, things are getting easier and nicer.
So we start by creating such cell array:
myStrings={'NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'};
where each cell contains a string. This will make your code more robust as well since every string can have a different length (this is not true if you concatenate all your strings in a matrix).
Then you specify which string you want to find inside such cell array:
stringThatMustBeTested='NACA64A010';
Now you can use cellfun(), which is a function that applies another function to every cell of a given cell array as follows:
results=cellfun(#(x) strcmp(x,stringThatMustBeTested),myStrings);
Such line simply means "apply strcmp() to every generic cell x inside myStrings and compare the cell with stringThatMustBeTested".
Variable results will be a logical output in which element j will be true if the j-th cell in your cell array is equal to the string you want to test. If results is entirely composed by 1s (which you can check as if sum(results)==length(results)), then all the strings are the same in myStrings (given that stringThatMustBeTested is the unique string in your cell array but anyways, this solution can be extended to a broader string search inside a cell).

Repeated array sampling yields duplicates. Why? (Ruby)

In Ruby:
I sample element from array. I see duplicate (same element) every 30 samples or so. Sometimes as close as 5-6 samples apart. Why?
This is my code:
some_array = IO.readlines("file with 5000 unique elements")
some_array.shuffle!
#random_element = some_array.sample
puts #random_element
If you want n random non-duplicate elements from your array, you should call some_array.sample(n).
Sample doesn't guarantee that two consecutive calls will not contain duplicates; it guarantees that all elements chosen in one call won't.

Reallocating/Erasing numpy array vs. new allocation in loop

In my program I need to work with arrays roughly 500x500 to 1500x1500 within a function that is looped over 1000's of times. In each iteration, I need to start with an array that has the same form (whose dimensions are fixed across all iterations). The initial values will be:
[0 0 0 ... 1]
[0 0 0 ... 1]
....
However, the contents of the array will be modified within the loop. What is the most efficient way to "reset" the array to this format so I can pass the same array to the function every time without having to allocate a new set of memory every time? (I know the range of rows that were modified)
I have tried:
a[first_row_modified:last_row_modified,:] = 0.
a[first_row_modified:last_row_modified,:-1] = 1.
but it takes roughly the same amount of time as just creating a new array every time with the following:
a = zeros((sizeArray, sizeArray))
a[:,-1] = 1.
Is there a faster way to effectively "erase" the array and change the last column to ones? I think this is similar to this question, clearing elements of numpy array , although my array doesn't change sizes and i didn't see the definitive answer to the previously asked question.
No; I think the way you are doing it is about as fast as it gets.

Resources