Related
Let's say I have a nested list:
list = [[10, 2, 8, 4], [12, 6, 4, 1], [8, 4, 3, 2], [9, 3, 4, 6]]
I want to rank the elements in the sublist against each other to create a new nested list with the rankings.
result = [[1, 4, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4], [1, 4, 3, 2]]
in the first sublist 10 would be 1st, 8 2nd, etc.
There are already some good solutions. Here just another one - functional approach for reference:
No 3rd library used.
lst = # your lists - don't use builtin "list"
def ranking(nums):
ranks = {x:i for i, x in enumerate(sorted(nums, reverse=True),1)}
return [ranks[x] for x in nums] # quick mapping back: O(1)
Calling it:
result = list(map(ranking, lst))
As already mentioned in the comment, you can use numpy.argsort, using it twice gives you the rank for the values, which need to be subtracted from len of the sub list to rank from highest to lowest, you can use List-Comprehension to do it for all the sub lists.
>>> import numpy as np
>>> lst = [[10, 2, 8, 4], [12, 6, 4, 1], [8, 4, 3, 2], [9, 3, 4, 6]]
>>> [(len(sub)-np.argsort(sub).argsort()).tolist() for sub in lst]
[[1, 4, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4], [1, 4, 3, 2]]
You can even use 2D numpy array and negate the values, then directly call argsort twice on the resulting array, and finally add 1:
>>> (-np.array(lst)).argsort().argsort()+1
array([[1, 4, 2, 3],
[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 4, 3, 2]], dtype=int64)
You can use scipy.stats.rankdata:
my_list = [[10, 2, 8, 4], [12, 6, 4, 1], [8, 4, 3, 2], [9, 3, 4, 6]]
from scipy.stats import rankdata
[list(len(l)+1-rankdata(l).astype(int)) for l in my_list]
output:
[[1, 4, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4], [1, 4, 3, 2]]
Without numpy/scipy:
[[sorted(li, reverse=True).index(x)+1 for x in li] for li in data]
[[1, 4, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4], [1, 4, 3, 2]]
Another solution with no external libraries, and with a better time complexity, just in case your sublists are a bit longer than 4 items (this has some overhead but I presume it is O(n log n) because of the call to sorted).
def rank_all(ls):
result = []
for subls in ls:
pairs = sorted([(subls[j],j) for j in range(len(subls))], reverse=True)
ranked = [0] * len(subls)
for j,p in enumerate(pairs):
ranked[p[1]]=j+1
result.append(ranked)
return result
I have this list:
victories = [[0, 7], [1, 2], [2, 3], [3, 6], [4, 7]]
I have to return all the first sub-elements, so 0, 1, 2, 3, 4
BUT
I need to sort the list according whom has the higher second sub-element, thus 7, 7, 6, 3, 2
If a first sub-element has the same second sub-element of another first sub-element, then who is lower is ranked before.
so the final list must be:
[0, 4, 3, 2, 1]
How can I do that?
You can try this one out using sorted and sort on second element first and then first like below
victories = [[0, 7], [1, 2], [2, 3], [3, 6], [4, 7]]
[i[0] for i in sorted(victories,key=lambda x : (-x[1],x[0]))]
I'm new to Python and could use some help. I tried to find a similar question but apparently, they differ by a bit and the answers don’t work for my problem. I use PyCharm and Python 3.8.
Cutting to the case:
I have a list of matrices and I want to average all the matrix values. I already struggle with accessing the values.
A small test list looks like this:
data = [[[1, 2, 3], [1, 2, 3], [1, 2, 3]],
[[2, 3, 4], [2, 3, 4], [2, 3, 4]],
[[3, 4, 5], [3, 4, 5], [3, 4, 5]],
[[4, 5, 6], [4, 5, 6], [4, 5, 6]]]
I tried to access all values at position (n, m) in the list and expect something like for (1,1) [2,3,4,5]
I tried to use:
print(data[:][1][1])
And got the result:
[2, 3, 4] which is one list entry short. Also, I think it's just data[1][1].
Which is not what I want to have.
Can someone tell me what I’m doing wrong?
When working with matrices in python I advice using numpy.
Your data is a list of four 3x3 matrices:
data = [
[
[1, 2, 3],
[1, 2, 3],
[1, 2, 3]
],
[
[2, 3, 4],
[2, 3, 4],
[2, 3, 4]
],
[
[3, 4, 5],
[3, 4, 5],
[3, 4, 5]
],
[
[4, 5, 6],
[4, 5, 6],
[4, 5, 6]
],
]
We can easily convert this to a numpy array:
import numpy as np
data_np = np.array(data)
print(data_np.shape)
the last statement returns (4, 3, 3) -- equivalent structure to your data, a 3-dimensional array, where the first is index of a matrix, and the last two are indices of elements of each matrix. Now you can subsample along any dimension, including your desired result:
data_np[:, 1, 1]
which returns array([2, 3, 4, 5]). You can also cast it to a python list if needed through data_np[:, 1, 1].tolist()
There's also a pure python version of this, which I do not recommend using, but it might be a useful design pattern in less obvious cases. Using list comprehension we access each matrix, and then retrieve the interesting index.
[matrix[1][1] for matrix in data]
which returns a list [2, 3, 4, 5]
I suggest using the numpy package, which is great for doing all sorts of matrix and vector operations. It makes indexing alot easier.
Note that i added some enters in your data array to make it more readible.
Example:
import numpy as np
data = np.array(
[
[[1,2,3],[1,2,3],[1,2,3]],
[[2,3,4],[2,3,4],[2,3,4]],
[[3,4,5],[3,4,5],[3,4,5]],
[[4,5,6],[4,5,6],[4,5,6]]
]
)
print(data[:,1,1])
Outputs:
[2 3 4 5]
lists cannot be indexed in the same way as numpy arrays.
Have a look what is happening with your slices:
The first slice is just returning the whole list
data[:]
[[[1, 2, 3], [1, 2, 3], [1, 2, 3]],
[[2, 3, 4], [2, 3, 4], [2, 3, 4]],
[[3, 4, 5], [3, 4, 5], [3, 4, 5]],
[[4, 5, 6], [4, 5, 6], [4, 5, 6]]]
the second slice is returning the second list (list indexes start at 0, so the index 1 is the second element)
data[:][1]
Out[46]: [[2, 3, 4], [2, 3, 4], [2, 3, 4]]
The third slice is returning the second list, within the second list
data[:][1][1]
Out[47]: [2, 3, 4]
If you want to achieve what you are looking for with a list, you would use:
[x[1][1] for x in data]
[2, 3, 4, 5]
to loop through each list and select the second element of the first list.
However, it would be better to use numpy
import numpy as np
arr = np.array(data)
arr[:, 1, 1]
Out[56]: array([2, 3, 4, 5])
I have a nested list, like this one:
[[2, 4], [1, 2], [2, 5], [3, 4], [3, 10], [2, 3, 4]]
From the nested list, I want to take the max value from index 0 list and assign it to the index 1 list. Similarly, I take the max value from index 2 list and assign it to the index 3 list. Similarly it goes,like this should be the output:
{4: [1,2], 5:[3,4], 10: [2,3,4]}
Is there any possible way of doing this in Python 3?
You can zip together offset even strides of the list.
I think this is what you want:
a = [[2, 4], [1, 2], [2, 5], [3, 4], [3, 10], [2, 3, 4]]
{max(x): y for x,y in zip(a[::2], a[1::2])}
# returns:
{4: [1, 2], 5: [3, 4], 10: [2, 3, 4]}
I have a list of lists and I'm looking for the shortest way of converting that data to a string where every inner list appears on a new line.
Assuming my input list is:
l_2d = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
I want my output to be a string (let's call it l_2d_str), so that if i print l_2d_str, I get:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
How about this?
l_2d = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
l_2d_str = '\n'.join(map(repr, l_2d))