How to find indexes of max n values in array - arrays

I have an array [0, 0, 10, 0, 3, 1]. I want to have the indexes of max three elements from this array, which would be: [2, 4, 5].
How do I do it without finding max element, delete it (make 0), then find next one, delete it and at last find third one? I can't sort this array, I need index from the current position.

a = [0, 0, 10, 0, 3, 1]
a.each_index.max_by(3){|i| a[i]} # => [2, 4, 5]
or
[0, 0, 10, 0, 3, 1].each_with_index.max(3).map(&:last) # => [2, 4, 5]

arr = [1, 3, 2, 4]
n = 2
p arr.each_with_index.sort.map(&:last).last(n).reverse
#=> [3,1]
How does it work ?
arr.each_with_index.sort
Will return an array of arrays. Each of the arrays is constructed as follows [value, index] and they are sorted based on value. In our example it would return [[1, 0], [2, 2], [3, 1], [4, 3]].
arr.map(&:last)
Will loop through all of those arrays and take the last value of the array (the index) and return an array of those indexes. In our example it will return [0, 2, 1, 3]. Now we have an array of indexes sorted in ascending order so the first value is the minimum and the last value is the maximum.
arr.last(n)
Returns an array containing last n values of an array. Since the array is in ascending order the max n values are the last n values.
arr.reverse
Reverts an array. It is optional. If you want to have the max in first position of your array and the Nth maximum value at the end then use reverse, else do not use it.

Related

How would you split a numpy array where the elements give the partition size?

For an numpy 1d array such as:
In [1]: A = np.array([2,5,1,3,9,0,7,4,1,2,0,11])
In [2]: A
Out[2]: array([2,5,1,3,9,0,7,4,1,2,0,11])
I need to split the array by using the values as a sub-array length.
For the example array:
The first index has a value of 2, so I need the first split to occur at index 0 + 2, so it would result in ([2,5,1]).
Skip to index 3 (since indices 0-2 were gobbled up in step 1).
The value at index 3 = 3, so the second split would occur at index 3 + 3, and result in ([3,9,0,7]).
Skip to index 7
The value at index 7 = 4, so the third and final split would occur at index 7 + 4, and result in ([4,1,2,0,11])
I'm using this simple array as an example, because I think it will help in my actual use case, which is reading data from binary files (either as bytes or unsigned shorts). I'm guessing that numpy will be the fastest way to do it, but I could also use struct/bytearray/lists or whatever would be best.
I hope this makes sense. I had a hard time trying to figure out how best to word the question.
Here is an approach using standard python lists and a while loop:
def custom_partition(arr):
partitions = []
i = 0
while i < len(arr):
pariton_size = arr[i]
next_i = i + pariton_size + 1
partitions.append(arr[i:next_i])
i = next_i
return partitions
a = [2, 5, 1, 3, 9, 0, 7, 4, 1, 2, 0, 11]
b = custom_partition(a)
print(b)
Output:
[[2, 5, 1], [3, 9, 0, 7], [4, 1, 2, 0, 11]]

get array index from sort in Ruby

I have an array
array_a1 = [9,43,3,6,7,0]
which I'm trying to get the sort indices out of, i.e. the answer should be
array_ordered = [6, 3, 4, 5, 1, 2]
I want to do this as a function, so that
def order (array)
will return array_ordered
I have tried implementing advice from Find the index by current sort order of an array in ruby but I don't see how I can do what they did for an array :(
if there are identical values in the array, e.g.
array_a1 = [9,43,3,6,7,7]
then the result should look like:
array_ordered = [3, 4, 5, 6, 1, 2]
(all indices should be 0-based, but these are 1-based)
You can do it this way:
[9,43,3,6,7,0].
each_with_index.to_a. # [[9, 0], [43, 1], [3, 2], [6, 3], [7, 4], [0, 5]]
sort_by(&:first). # [[0, 5], [3, 2], [6, 3], [7, 4], [9, 0], [43, 1]]
map(&:last)
#=> [5, 2, 3, 4, 0, 1]
First you add index to each element, then you sort by the element and finally you pick just indices.
Note, that array are zero-indexed in Ruby, so the results is less by one comparing to your spec.
You should be able to just map over the sorted array and lookup the index of that number in the original array.
arr = [9,43,3,6,7,0]
arr.sort.map { |n| arr.index(n) } #=> [5, 2, 3, 4, 0, 1]
Or if you really want it 1 indexed, instead of zero indexed, for some reason:
arr.sort.map { |n| arr.index(n) + 1 } #=> [6, 3, 4, 5, 1, 2]
array_a1 = [9,43,3,6,7,0]
array_a1.each_index.sort_by { |i| array_a1[i] }
#=> [5, 2, 3, 4, 0, 1]
If array_a1 may contain duplicates and ties are to be broken by the indices of the elements (the element with the smaller index first), you may modify the calculation as follows.
[9,43,3,6,7,7].each_index.sort_by { |i| [array_a1[i], i] }
#=> [2, 3, 4, 5, 0, 1]
Enumerable#sort_by compares two elements with the spaceship operator, <=>. Here, as pairs of arrays are being compared, it is the method Array#<=> that is used. See especially the third paragraph of that doc.

Assign 1 and 0 values to numpy array depending on whether values are in list

I am looking for a way to filter numpy arrays based on a list
input_array = [[0,4,6],[2,1,1],[6,6,9]]
list=[9,4]
...
output_array = [[0,1,0],[0,0,0],[0,0,1]]
I am currently flattening the array, and turning it to a list and back. Looks very unpythonic:
list=[9,4]
shape = input_array.shape
input_array = input_array.flatten()
output_array = np.array([int(i in list) for i in input_array])
output_array = output_array.reshape(shape)
We could use np.in1d to get the mask of matches. Now, np.in1d flattens the input to 1D before processing. So, the output from it is to be reshaped back to 2D and then converted to int for an output with 0s and 1s.
Thus, the implementation would be -
np.in1d(input_array, list).reshape(input_array.shape).astype(int)
Sample run -
In [40]: input_array
Out[40]:
array([[0, 4, 6],
[2, 1, 1],
[6, 6, 9]])
In [41]: list=[9,4]
In [42]: np.in1d(input_array, list).reshape(input_array.shape).astype(int)
Out[42]:
array([[0, 1, 0],
[0, 0, 0],
[0, 0, 1]])

Unintuitive behaviour of array.map

So this behaviour seems to be logical
> array = (1..4).to_a
=> [1, 2, 3, 4]
> array.map {|a| [array.delete(array.first), array.delete(array.last)]}
=> [[1, 4], [2, 3]]
> array
=> []
But then when we increase the range it doesn't work:
> array = (1..6).to_a
=> [1, 2, 3, 4, 5, 6]
> array.map {|a| [array.delete(array.first), array.delete(array.last)]}
=> [[1, 6], [2, 5]]
> array
=> [3, 4]
And it does the same weird behaviour with odd numbers:
> array = (1..9).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
> array.map {|a| [array.delete(array.first), array.delete(array.last)]}
=> [[1, 9], [2, 8], [3, 7]]
> array
=> [4, 5, 6]
This was not what we expected, why does it behave this way?
This is a guess since I am not sure if this is the exact case but I can't put this as a comment.
So lets go step by step:
you defined an array:
> array = (1..6).to_a
=> [1, 2, 3, 4, 5, 6]
Now defined an iterator:
array.map {|a| [array.delete(array.first), array.delete(array.last)]}
so for first iteration it will take array[0] as the value for for variable a and do the operation and hence deleting first and last element of the array.
After first iteration array becomes [2,3,4,5].
For second iteration it will take array[1] as the value for for variable a and do the same as in first iteration and delete first and last element. Now array is [3,4].
Now for 3rd iteration, well it would not have tried for 3rd iteration if your original array was only size of 2 i.e like [2,3] but since you modified your original array during iteration so it will attempt 3rd iteration since original array had length 6.
For 3rd iteration it needs array's third element i.e array[2] but your current array does not have that index so it returns the remaining array without any other operation.
It is really confusing to modify array while being iterated.

Sort array based on frequency

How can I sort an array by most repetitive values.?
suppose I have an array [3, 3, 3, 3, 4, 4]
Expected the result as [3, 4] since 3 is most repeated and 4 is least repeated.
Is there any way too do it?
Thanks in advance....!
Here is one way of doing it:
distictList: Get all distinct values from the array and store in this
countArray: For each ith index in distinctList countArray[i] holds the occurrence of the distinctList[i]
Now sort countArray and apply same swaps on the distinctList simultaneously.
Ex: [3, 3, 4, 4, 4]
distinctList [3,4]
countArray [2,3]
Descending sort countArray [3,2] sorting distinctList at the same time [4,3]
Output: [4, 3]`
Simple in Python:
data = [3, 2, 3, 4, 2, 1, 3]
frequencies = {x:0 for x in data}
for x in data:
frequencies[x] = frequencies[x] + 1
sorted_with_repetitions = sorted(data, key=lambda x:frequencies[x],reverse=True)
sorted_without_repetitions = sorted(frequencies.keys(), key=lambda x:frequencies[x],reverse=True)
print(data)
print(sorted_with_repetitions)
print(sorted_without_repetitions)
print(frequencies)
The same approach (an associative container to collect distinct values and count occurrences, used in a custom comparison to sort an array with the original data or only distinct items) is suitable for Java.

Resources