Using nested lists like this:
N = [['D','C','A','B'],
[2,3,4,5],
[6,7,8,9]]
How could I swap two columns? for instance column C and column A.
With a for loop and a little help from this post:
Code:
N = [["D","C","A","B"],
[2,3,4,5],
[6,7,8,9]]
# Swap the last two columns
for item in N:
item[2], item[3] = item[3], item[2]
# Or as a function
def swap_columns(your_list, pos1, pos2):
for item in your_list:
item[pos1], item[pos2] = item[pos2], item[pos1]
Output:
swap_columns(N, 2, 3)
[['D', 'C', 'B', 'A'], [2, 3, 5, 4], [6, 7, 9, 8]]
Another possibility, using zip:
In [66]: N = [['D', 'C', 'A', 'B'], [2, 3, 4, 5], [6, 7, 8, 9]]
Transpose using zip:
In [67]: M = list(zip(*N))
Swap rows 1 and 2:
In [68]: M[1], M[2] = M[2], M[1]
Transpose again:
In [69]: N2 = list(zip(*M))
In [70]: N2
Out[70]: [('D', 'A', 'C', 'B'), (2, 4, 3, 5), (6, 8, 7, 9)]
The result is a list of tuples. If you need a list of lists:
In [71]: [list(t) for t in zip(*M)]
Out[71]: [['D', 'A', 'C', 'B'], [2, 4, 3, 5], [6, 8, 7, 9]]
This doesn't make the swap in-place. For that, see #DaveTucker's answer.
>>> N = [['D','C','A','B'],
... [2,3,4,5],
... [6,7,8,9]]
>>>
>>> lineorder = 0,2,1,3
>>>
>>> [[r[x] for x in lineorder] for r in N]
[['D', 'A', 'C', 'B'], [2, 4, 3, 5], [6, 8, 7, 9]]
If you don't want the order hardcoded, you can generate it easily like this
>>> lineorder = [N[0].index(x) for x in ['D','A','C','B']]
To create a copy of N with two columns swapped, S, in one line, You could do the following:
>>> N = [['D','C','A','B'],[2,3,4,5],[6,7,8,9]]
>>> S = [[n[0],n[2],n[1],n[3]] for n in N]
>>> S
[['D', 'A', 'C', 'B'], [2, 4, 3, 5], [6, 8, 7, 9]]
This assumes that each nested list of N are equal in size.
l = [1, 2]
emptl = []
for item in l:
empl.append([item[1], item[0]])
Related
There are 2 lists and my goal is to add the element from one list before and after the delimiters of another list.
Below is the example:
ListA = ["A", "B"]
ListB = [[1, 2, 3, 4], [5, 6, 7, 8]]
Expected Output:
[[1, 'A', 2, 'A', 3, 'A', 4, 'A'], [5, 'B', 6, 'B', 7, 'B', 8, 'B']]
What I've done so far:
for x, y in zip(ListB, ListA):
x.append(y)
Output: ListB
[[1, 2, 3, 4, 'A'], [5, 6, 7, 8, 'B']]
Your code appends 'A' once to the whole [1,2,3,4] list.
This should work:
ListA = ['A','B']
ListB = [[1,2,3,4],[5,6,7,8]]
for x, y in zip(ListB, ListA):
for i in range(len(x)):
x.insert(2*i+1,y)
print(ListB)
# [[1, 'A', 2, 'A', 3, 'A', 4, 'A'], [5, 'B', 6, 'B', 7, 'B', 8, 'B']]
A variant to produce something closest to your 2nd demand:
ListA = ['A','B','C']
ListB = [[1,5],[2,10],[11,15]]
for x, y in zip(ListB, ListA):
for i in range(len(x)):
x[i] = y + ' ' + str(x[i])
print(ListB)
# [['A 1', 'A 5'], ['B 2', 'B 10'], ['C 11', 'C 15']]
zip the two lists together, and then build new lists out of pairs of all the b items with the single a item:
>>> ListA = ['A','B']
>>> ListB = [[1,2,3,4],[5,6,7,8]]
>>> [[j for t in ((i, a) for i in b) for j in t] for a, b in zip(ListA, ListB)]
[[1, 'A', 2, 'A', 3, 'A', 4, 'A'], [5, 'B', 6, 'B', 7, 'B', 8, 'B']]
Here is another approach to this:
from itertools import repeat
ListA = ["A", "B"]
ListB = [[1, 2, 3, 4], [5, 6, 7, 8]]
result = []
for x, y in zip(ListA, ListB):
nested_list = []
for item in zip(y, repeat(x)):
nested_list.extend(item)
result.append(nested_list)
print(result)
This can be written using a bit more complex list comp(Also this modifies ListB in-place instead of creating a new one):
from itertools import repeat
ListA = ["A", "B"]
ListB = [[1, 2, 3, 4], [5, 6, 7, 8]]
ListB[:] = [
[i for item in zip(y, repeat(x)) for i in item] for x, y in zip(ListA, ListB)
]
print(ListB)
Let's say I have a list:
list = [[1, 2, 3, 4],
['a', 'b', 'c', 'd'],
[9, 8, 7, 6]]
and I would like to get something like:
newList = [[2, 3, 4],
['b', 'c', 'd'],
[8, 7, 6]]
hence I tried going with this solution
print(list[0:][1:])
But I get this output
[['a', 'b', 'c', 'd'],
[9, 8, 7, 6]]
Therefore I tried
print(list[1:][0:])
but I get precisely the same result.
I tried to make some research and experiments about this specific subject but without any result.
You want the 1 to end element of every row in your matrix.
mylist = [[1, 2, 3, 4],
['a', 'b', 'c', 'd'],
[9, 8, 7, 6]]
new_list = [row[1:] for row in mylist]
I want explain, what have you done by this
print(list[0:][1:])
print(list[1:][0:])
Firstly note that python use indices starting at 0, i.e. for [1,2,3] there is 0th element, 1th element and 2nd element.
[0:] means get list elements starting at 0th element, this will give you copy of list, [1:] means get list elements starting at 1th element, which will give you list with all but 0th element. Therefore both lines are equivalent to each other and to
print(list[1:])
You might desired output using comprehension or map as follows
list1 = [[1, 2, 3, 4], ['a', 'b', 'c', 'd'], [9, 8, 7, 6]]
list2 = list(map(lambda x:x[1:],list1))
print(list2)
output
[[2, 3, 4], ['b', 'c', 'd'], [8, 7, 6]]
lambda here is nameless function, note that comprehension here is more readable, but might be easier to digest if you earlier worked with language which have similar feature, e.g. JavaScript's map
First - don't name your list "list"!
a = [[1, 2, 3, 4],
['a', 'b', 'c', 'd'],
[9, 8, 7, 6]]
b = [x[1:] for x in a]
print(b)
[[2, 3, 4], ['b', 'c', 'd'], [8, 7, 6]]
I want to sort a list of lists ie:
[['Y', 'K', 'E'],
[3, 1, 2],
[6, 4, 5]]
The first row of that list should match another supplied list (this list will always containing matching letters to the first row of the first list):
['K', 'E', 'Y']
So that the final output is:
[['K', 'E', 'Y'],
[1, 2, 3],
[4, 5, 6]]
The easy way is to transpose it with zip(), sort it with a key of the first element's index in the key list, then transpose it back:
>>> data = [['Y', 'K', 'E'],
... [3, 1, 2],
... [6, 4, 5]]
>>> key = 'KEY'
>>> sorted(zip(*data), key=lambda x: key.index(x[0]))
[('K', 1, 4), ('E', 2, 5), ('Y', 3, 6)]
>>> list(zip(*sorted(zip(*data), key=lambda x: key.index(x[0]))))
[('K', 'E', 'Y'), (1, 2, 3), (4, 5, 6)]
A pretty straightforward approach using list comprehensions:
>>> L = [['Y', 'K', 'E'], [3, 1, 2], [6, 4, 5]]
>>> indexes = [L[0].index(x) for x in "KEY"]
>>> [[row[i] for i in indexes] for row in L]
[['K', 'E', 'Y'], [1, 2, 3], [4, 5, 6]]
I have these lists:
l1 = ["foo","bar","x","y","z","x","y","z","x","y","z"]
l2 = ["foo","bar","w","x","y","z","w","x","y","z","w","x","y","z"]
l3 = ["foo","bar","y","z","y","z","y","z"]
For each of the list above I'd like to get the indices of sequential chunks
from 3rd entry onwards. Yield:
l1_indices = [[2,3,4],[5,6,7],[8,9,10]]
l2_indices = [[2,3,4,5],[6,7,8,9],[10,11,12,13]]
l3_indices = [[2,3],[4,5],[6,7]]
To clarify further, I got l1_indices the following way:
["foo","bar", "x","y","z", "x","y","z", "x","y","z"]
0 1 2 3 4 5 6 7 8 9 10 <-- indices id
---> onwards
---> always in 3 chunks
What's the way to do it in Python?
I tried this but no avail:
In [8]: import itertools as IT
In [9]: import operator
In [11]: [list(zip(*g))[::-1] for k, g in IT.groupby(enumerate(l1[2:]), operator.itemgetter(1))]
Out[11]:
[[('x',), (0,)],
[('y',), (1,)],
[('z',), (2,)],
[('x',), (3,)],
[('y',), (4,)],
[('z',), (5,)],
[('x',), (6,)],
[('y',), (7,)],
[('z',), (8,)]]
If sequential elements are always in three chunks and always starts from third item then you can simply divide the remaining elements by three and generate indices list.
>>> def get_indices(l):
... last = len(l) - 2
... diff = last / 3
... return [range(i, i + diff) for i in range(2, last, diff)]
...
>>> get_indices(l1)
[[2, 3, 4], [5, 6, 7], [8, 9, 10]]
>>> get_indices(l2)
[[2, 3, 4, 5], [6, 7, 8, 9], [10, 11, 12, 13]]
>>> get_indices(l3)
[[2, 3], [4, 5]]
As a more general answer first of all you can find a sublist of your list that contain elements with length more than 1 , then based on its length and length of its set you can grub the desire indices :
>>> l =['foo', 'bar', 'w', 'x', 'y', 'z', 'w', 'x', 'y', 'z', 'w', 'x', 'y', 'z']
>>> s=[i for i in l if l.count(i)>2]
>>> len_part=len(l)-len(s)
>>> len_set=len(set(s))
>>> [range(i,i+l_s) for i in range(len_part,len(l),len_set)]
[[2, 3, 4, 5], [6, 7, 8, 9], [10, 11, 12, 13]]
How do I sort a multidimensional list to alphabetical order based on its first row of data without using numpy nor other modules
For example I have a list:
[['M', 'A', 'R', 'K']
[1, 3, 5, 4]
[2, 6, 7, 8]]
I want it to be like:
[['A', 'K', 'M', 'R']
[3, 4, 1, 5]
[6, 8, 2, 7]]
Thanks!
I think there should be a better way; anyway, this would do the trick:
>>> l = [['M', 'A', 'R', 'K'], [1, 3, 5, 4], [2, 6, 7, 8]]
>>> sorted_l = map(list, zip(*sorted(zip(*l))))
>>> print(list(sorted_l))
[['A', 'K', 'M', 'R'], [3, 4, 1, 5], [6, 8, 2, 7]]
Edit:
zip(*l) gives you an iterator (in Python 3), if you do [i for i in zip(*l)], you'll find it looks like [('M', 1, 2), ('A', 3, 6), ('R', 5, 7), ('K', 4, 8)]
sorted(zip(*l)) sorts the list above (becomes [('A', 3, 6), ('K', 4, 8), ('M', 1, 2), ('R', 5, 7)] under the hood), I didn't specify the key, so it compares the elements directly
then, you zip again, and you get an iterator of what you wants (elements in l are ('A', 'K', 'M', 'R'), (3, 4, 1, 5), (6, 8, 2, 7) if you print them out); however, you have to do map() so you can get <class 'list'> instead of <class 'tuple'>
finally, map() also returns an iterator in Python3, to get a list, you simply use list([iterable]) to construct the final list.
Documentations: zip, sorted, and map
Once you know the new "order" (or mapping) of the sorted indexes, you should be able to use operator.itemgetter to basically walk all the rows and get the items in the order that you just found.
In your case, you have ['M', 'A', 'R', 'K']. In order to get those letters sorted, you should first get index 1, then index 3, then index 0 and finally index 2: (A K M R). Once you find that mapping, you can just call itemgetter to get you the items on each row in that order.
import operator
a=[
['M', 'A', 'R', 'K'],
[1, 3, 5, 4],
[2, 6, 7, 8],
]
sorted_first = sorted(a[0])
sorted_indexes = [a[0].index(letter) for letter in sorted_first]
print "Mapping: %s" % sorted_indexes
new_sorted = [operator.itemgetter(* sorted_indexes)(line) for line in a]
print new_sorted
Which ouputs:
Mapping: [1, 3, 0, 2]
[('A', 'K', 'M', 'R'),
(3, 4, 1, 5),
(6, 8, 2, 7)]
EDIT:
rpatisso made me see (in comments to this answer) that there's more effective way to calculate the sorted_indexes variable than using list.index which is O(n2):
sorted_indexes = sorted(range(len(a[0])), key=lambda i: a[0][i])
Try it with numpy.
>>> import numpy as np
>>> a = np.array([['M', 'A', 'R', 'K'],
... [1, 3, 5, 4],
... [2, 6, 7, 8]], dtype=object)
>>> a[:,np.argsort(a[0])]
array([['A', 'K', 'M', 'R'],
[3, 4, 1, 5],
[6, 8, 2, 7]], dtype=object)
Without numpy:
>>> map(list,zip(*sorted(zip(*a))))
[['A', 'K', 'M', 'R'], [3, 4, 1, 5], [6, 8, 2, 7]]