Python - How to sort multidimensional list to two-dimensional list?
The idea is basically the same that the one in @TerryA answer, but using setdefault and checking at the end of the for loop if something of the depth was added:
lst = [8, [6, 7, [-1], [4, [[10]]], 2], 1]
def depths(l):
def flatten(l, start=0, depth={}):
for e in l:
if isinstance(e, list):
flatten(e, start=start + 1, depth=depth)
else:
depth.setdefault(start, []).append(e)
if start not in depth:
depth[start] = []
d = {}
flatten(l, depth=d)
return [d[i] for i in range(max(d) + 1)]
result = depths(lst)
print(result)
Output
[[8, 1], [6, 7, 2], [-1, 4], [], [10]]
How to sort two dimensional list while giving priority along one of the dimension
You need to consider both values in the same sort key. Normally, Python would sort by the [0]
value, then by the [1]
value. We can make use of this by creating a key that reverses the values:
sorted(twod_list,key=lambda l:(l[1], l[0]))
Now Python will sort first according to the [0]
of the key, which is [1]
of the original, and then according to the [1]
of the key, which is [0]
of the original.
How to sort a 2 dimensional list in python
Well, i dug a little in stackoverflow questions and found the most suitable answer for me:
https://stackoverflow.com/a/7588949/13077523
From the Python documentation wiki, I think you can do:
a = ([[1, 2, 3], [4, 5, 6], [0, 0, 1]]);
a = sorted(a, key=lambda a_entry: a_entry[1])
print a
The output is:
[[[0, 0, 1], [1, 2, 3], [4, 5, 6]]]
But what i instead did is:
get_results = search(input('Please enter a movie name: '))
get_results = sorted(get_results, key=lambda a_entry: a_entry['year'])
count = -1
table = []
for a in get_results:
count += 1
entry = [count, a['title'], a['year']]
table.append(entry)
headers = ['SlNo', "Title", "Year"]
table = tabulate(table, headers, tablefmt='psql')
table = '\n'.join(table.split('\n')[::-1])
click.echo(table)
Which worked perfectly for me!
how to sort a multidimensional array with one column in ascending order and another column in descending order?
You can use the key
but with a small change, and using -
counts as "descending" (negative numbers always come before positive numbers in an ascending order sort). So you don't have to use the reverse
parameter at all.
>>> sorted(students, key = lambda x:(-x[2], x[1]))
[[2, 'Rose', 13], [3, 'Jack', 12], [5, 'Sam', 12], [1, 'Tom', 10], [4, 'Joy', 8]]
How to sort multidimensional array by column?
Yes. The sorted
built-in accepts a key
argument:
sorted(li,key=lambda x: x[1])
Out[31]: [['Jason', 1], ['John', 2], ['Jim', 9]]
note that sorted
returns a new list. If you want to sort in-place, use the .sort
method of your list (which also, conveniently, accepts a key
argument).
or alternatively,
from operator import itemgetter
sorted(li,key=itemgetter(1))
Out[33]: [['Jason', 1], ['John', 2], ['Jim', 9]]
Read more on the python wiki.
Sort two dimensional list python
I'm not sure this is a sorting problem; it's more of a grouping one (or optimization?)
Sorting requires some criteria for putting the [45,205] list before [42,206]. key
works if you can come up with one number that represents the desired order.
For example calculate the distance from the origin
A = np.array(a)
creates a numpy array:
In [346]: A
Out[346]:
array([[ 42, 206],
[ 45, 40],
[ 45, 205],
[ 46, 41],
[ 46, 205],
[ 47, 40],
[ 47, 202],
[ 48, 40],
[ 48, 202],
[ 49, 38]])
distance or radius in polar coordinates is sum of squares (sqrt
isn't needed for this purpose). Applying argsort
to this ranks the points by distance from origin.
In [347]: np.sum(A**2,axis=1)
Out[347]: array([44200, 3625, 44050, 3797, 44141, 3809, 43013, 3904, 43108, 3845])
In [348]: r = np.sum(A**2,axis=1)
In [349]: idx = np.argsort(r)
In [350]: idx
Out[350]: array([1, 3, 5, 9, 7, 6, 8, 2, 4, 0], dtype=int32)
In [351]: A[idx,:]
Out[351]:
array([[ 45, 40],
[ 46, 41],
[ 47, 40],
[ 49, 38],
[ 48, 40],
[ 47, 202],
[ 48, 202],
[ 45, 205],
[ 46, 205],
[ 42, 206]])
The list equivalent operation uses a key function like
def foo(xy):
x,y=xy
return x**2+y**2
In [356]: sorted(a, key=foo)
Out[356]:
[[45, 40],
[46, 41],
[47, 40],
[49, 38],
[48, 40],
[47, 202],
[48, 202],
[45, 205],
[46, 205],
[42, 206]]
Pairwise distances
In numpy
it's fairly easy to come up with pairwise distance (even easier with one of the scipy
tools). But what would you do with those? What defines order based on such distances?
For example to use the kind of iteration that we are often asked to 'vectorize':
In [369]: D = np.zeros((10,10))
In [370]: for i in range(10):
...: for j in range(i,10):
...: D[i,j] = np.sqrt(sum((A[i,:]-A[j,:])**2))
# D[i,j] = np.linalg.norm(A[i,:]-A[j,:])
In [372]: D.astype(int)
Out[372]:
array([[ 0, 166, 3, 165, 4, 166, 6, 166, 7, 168],
[ 0, 0, 165, 1, 165, 2, 162, 3, 162, 4],
[ 0, 0, 0, 164, 1, 165, 3, 165, 4, 167],
[ 0, 0, 0, 0, 164, 1, 161, 2, 161, 4],
[ 0, 0, 0, 0, 0, 165, 3, 165, 3, 167],
[ 0, 0, 0, 0, 0, 0, 162, 1, 162, 2],
[ 0, 0, 0, 0, 0, 0, 0, 162, 1, 164],
[ 0, 0, 0, 0, 0, 0, 0, 0, 162, 2],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 164],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
is a matrix of distances, rounded for ease of display.
numpy has a lexical sort. We could use that to sort on the 2nd coordinate first, and then the 1st coor. That would group all those 200's together:
In [375]: np.lexsort(A.T)
Out[375]: array([9, 1, 5, 7, 3, 6, 8, 2, 4, 0], dtype=int32)
In [376]: A[_,:]
Out[376]:
array([[ 49, 38],
[ 45, 40],
[ 47, 40],
[ 48, 40],
[ 46, 41],
[ 47, 202],
[ 48, 202],
[ 45, 205],
[ 46, 205],
[ 42, 206]])
pairwise distances with that sorted array look like:
array([[ 0, 4, 2, 2, 4, 164, 164, 167, 167, 168],
[ 0, 0, 2, 3, 1, 162, 162, 165, 165, 166],
[ 0, 0, 0, 1, 1, 162, 162, 165, 165, 166],
[ 0, 0, 0, 0, 2, 162, 162, 165, 165, 166],
[ 0, 0, 0, 0, 0, 161, 161, 164, 164, 165],
[ 0, 0, 0, 0, 0, 0, 1, 3, 3, 6],
[ 0, 0, 0, 0, 0, 0, 0, 4, 3, 7],
[ 0, 0, 0, 0, 0, 0, 0, 0, 1, 3],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 4],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
Search over permutations
Another way of thinking of this problem is as a search problem, for example seeking to find the order of points that minimizes the 'travel' distance, i.e. the sum of distances between successive points.
With the original a
(A
), the distance (with default np.linalg.norm
method) between successive points is
In [407]: np.linalg.norm(A[1:]-A[:-1],axis=1)
Out[407]:
array([ 166.02710622, 165. , 164.00304875, 164. ,
165.00303028, 162. , 162.00308639, 162. ,
164.00304875])
and their sum:
In [408]: _.sum()
Out[408]: 1474.0393203904973
With the lexsort
order
In [410]: np.linalg.norm(A1[1:]-A1[:-1],axis=1)
Out[410]:
array([ 4.47213595, 2. , 1. , 2.23606798,
161.00310556, 1. , 4.24264069, 1. ,
4.12310563])
In [411]: _.sum()
Out[411]: 181.07705580534656
Clearly this has better clustering, mainly based on the 2nd column values.
Your sorted_a
improves this sum a bit:
In [414]: sortedA = np.array(sorted_a)
In [415]: np.linalg.norm(sortedA[1:]-sortedA[:-1],axis=1)
Out[415]:
array([ 3.16227766, 4.12310563, 3.16227766, 1. ,
162.0277754 , 1.41421356, 1.41421356, 1. ,
2.23606798])
In [416]: _.sum()
Out[416]: 179.53993144488973
A brute force solution is to try all the permutations, and pick the one that minimizes this sum.
How to sort 2d array by row in python?
Python, per se, has no "2d array" -- it has (1d) lists as built-ins, and (1d) arrays in standard library module array. There are third-party libraries such as numpy
which do provide Python-usable multi-dimensional arrays, but of course you'd be mentioning such third party libraries if you were using some of them, rather than just saying "in Python", right?-)
So I'll assume that by "2d array" you mean a list of lists, such as:
lol = [ range(10), range(2, 12), range(5, 15) ]
or the like -- i.e. a list with 3 items, each item being a list with 10 items, and the "second row" would be the sublist item lol[1]
. Yeah, lots of assumptions, but your question is so maddeningly vague that there's no way to avoid making assumptions - edit your Q to clarify with more precision, and an example!, if you dislike people trying to read your mind (and probably failing) as you currently make it impossible to avoid.
So under these assumptions you can sort each of the 3 sublists in the order required to sort the second one, for example:
indices = range(10)
indices.sort(key = lol[1].__getitem__)
for i, sublist in enumerate(lol):
lol[i] = [sublist[j] for j in indices]
The general approach here is to sort the range of indices, then just use that appropriately sorted range to reorder all the sublists in play.
If you actually have a different problem, there will of course be different solutions;-).
Sorting a 2D list in python with conditions
Python's sort function is stable, which means that if two elements compare equal to each other, their relative positions don't change. Elements only switch positions if they compare unequal to each other.
Additionally, sorting takes an optional key
parameter, which is a function that determines which values the sort should compare. You can define a full function for this, but it's common to define a short lambda function if you're only going to use it once.
Put these together, and you can first sort the lists by their second elements, then sort them a second time by their first elements. The relative positions from the first sort will be maintained after the second.
a = [
['abc', 5],
['abd', 21],
['abb', 10],
['abc', 3],
['abb', 15],
['abd', 20]
]
# Sort by second element first, in descending order
a = sorted(a, key=lambda x: x[1], reverse=True)
# Then sort by first element, in ascending order
a = sorted(a, key=lambda x: x[0])
print(a) # [['abb', 15], ['abb', 10], ['abc', 5], ['abc', 3], ['abd', 21], ['abd', 20]]
Related Topics
Convert HTML String to an Image in Python
Changing Presence Discord Status
How to Save Opened Page as Pdf in Selenium (Python)
Python | Make the Percentage of a List
How to Convert .Dat to .Csv Using Python
Hiding Raw_Input() Password Input
How to Split an Integer into an Array of Digits
Tkinter Ttk Treeview How to Set Fixed Width Why It Change With Number of Column
How to Avoid Last Comma in Python Loop
How to Get Local Issuer Certificate When Using Requests in Python
How to Prevent Brokenpipeerror When Doing a Flush in Python
Selenium Python Send_Key Error: List Object Has No Attribute
In Python, How to Check If a Date Is Valid