How to index nested lists in Python? - python

I have a nested list as shown below:
A = [('a', 'b', 'c'),
('d', 'e', 'f'),
('g', 'h', 'i')]
and I am trying to print the first element of each list using the code:
A = [('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i')]
print A[:][0]
But I get the following output:
('a', 'b', 'c')
Required output:
('a', 'd', 'g')
How to get this output in Python?

A[:] just creates a copy of the whole list, after which you get element 0 of that copy.
You need to use a list comprehension here:
[tup[0] for tup in A]
to get a list, or use tuple() with a generator expression to get a tuple:
tuple(tup[0] for tup in A)
Demo:
>>> A = [('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i')]
>>> [tup[0] for tup in A]
['a', 'd', 'g']
>>> tuple(tup[0] for tup in A)
('a', 'd', 'g')

You can transpose a list of lists/tuples with zip(*list_of_lists) then select the items you want.
>>> a
[('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i')]
>>> b = zip(*a)
>>> b
[('a', 'd', 'g'), ('b', 'e', 'h'), ('c', 'f', 'i')]
>>> b[0]
('a', 'd', 'g')
>>>
>>> c = zip(*a)[0]
>>> c
('a', 'd', 'g')
>>>

You can also do it this way:
>>> A = [('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i')]
>>> map(lambda t:t[0], A)
['a', 'd', 'g']
>>> tuple(map(lambda t:t[0],A))
('a', 'd', 'g')

Python lists don't work very well as multi-dimensional arrays.
If you're willing to add an extra dependency(e.g. if you're going to do a lot of array manipulation), numpy allows you to use the almost the exact syntax you're looking for
import numpy as np
A = np.array([('a', 'b', 'c'),
('d', 'e', 'f'),
('g', 'h', 'i')])
This outputs the row as an np.array(which can be accessed like a list):
>>> A[:,0]
array(['a', 'd', 'g'])
To get the first row as a tuple:
>>> tuple(A[:,0])
('a', 'd', 'g')

You can also get the behavior you want using pandas as follows:
In [1]: import pandas as pd
In [2]: A = [('a', 'b', 'c'),
('d', 'e', 'f'),
('g', 'h', 'i')]
In [3]: df = pd.DataFrame(A)
In [4]: df[:][0]
Out[4]:
0 a
1 d
2 g
Name: 0, dtype: object
In [5]: df[:][0].values
Out[5]: array(['a', 'd', 'g'], dtype=object)

Related

How can I rearrange a set of values into new pattern on python and print results

so I will do my best to explain what I'm looking for,
at the moment I have a 100 item list that I want to repetitively shuffle using a set pattern to first check if the pattern will eventually bring me back to where I began
and 2 to print the result of each loop to a text file.
so using a 3 item list as my example
[a,b,c]
and the shuffle pattern [3 1 2]
where the 3rd item becomes the first.
the first item becomes the second
and the second item becomes the 3rd
on a loop would generate the following patterns
[a,b,c]
[3,1,2]
[c,a,b]
[b,c,a]
[a,b,c]
but I have a list at the moment of 100 items that I need to find every single arrangement for a few different patterns I would like to test out.
does anyone know of a way to do this in python please.
You can define function and call this function multi times like below:
>>> def func(lst, ptr):
... return [lst[idx-1] for idx in ptr]
>>> lst = ['a','b','c']
>>> ptr = [3,1,2]
>>> for _ in range(5):
... lst = func(lst, ptr)
... print(lst)
['c', 'a', 'b']
['b', 'c', 'a']
['a', 'b', 'c']
['c', 'a', 'b']
['b', 'c', 'a']
You could use numpy advanced integer indexing if your list contains a numeric type:
import numpy as np
original_list=[1,2,3]
numpy_array = np.array(original_list)
pattern = [2,1,0]
print(numpy_array[pattern])
>>> array([3, 2, 1])
def rearrange(pattern : list,L:list):
new_list = []
for i in pattern :
new_list.append(L[i-1])
return new_list
print(rearrange([3,1,2],['a','b','c']))
output :
['c', 'a', 'b']
Itertools could be what you need.
import itertools
p = itertools.permutations(['a','b','c', 'd'])
list(p)
Output:
[('a', 'b', 'c', 'd'),
('a', 'b', 'd', 'c'),
('a', 'c', 'b', 'd'),
('a', 'c', 'd', 'b'),
('a', 'd', 'b', 'c'),
('a', 'd', 'c', 'b'),
('b', 'a', 'c', 'd'),
('b', 'a', 'd', 'c'),
('b', 'c', 'a', 'd'),
('b', 'c', 'd', 'a'),
('b', 'd', 'a', 'c'),
('b', 'd', 'c', 'a'),
('c', 'a', 'b', 'd'),
('c', 'a', 'd', 'b'),
('c', 'b', 'a', 'd'),
('c', 'b', 'd', 'a'),
('c', 'd', 'a', 'b'),
('c', 'd', 'b', 'a'),
('d', 'a', 'b', 'c'),
('d', 'a', 'c', 'b'),
('d', 'b', 'a', 'c'),
('d', 'b', 'c', 'a'),
('d', 'c', 'a', 'b'),
('d', 'c', 'b', 'a')]
​

How to return ordened array names?

I have an array I want to sort from low to high, but I want it to return the array names (G, F, H...) instead of just the numbers. How do I do this?
A=12.74087388
B=12.48817861
C=12.31249807
D=12.95688859
E=12.49693343
F=11.51090636
G=10.16505019
H=11.99872655
Array=np.array([A,B,C,D,E,F,G,H])
sort=np.sort(Array)
Use a dictionary:
d = dict(A=12.74087388,
B=12.48817861,
C=12.31249807,
D=12.95688859,
E=12.49693343,
F=11.51090636,
G=10.16505019,
H=11.99872655)
and sort by value:
>>> sorted(d, key=d.get)
['G', 'F', 'H', 'C', 'B', 'E', 'A', 'D']
or keep the numbers and sort by value:
from operator import itemgetter
print(sorted(d.items(), key=itemgetter(1)))
Output:
[('G', 10.16505019),
('F', 11.51090636),
('H', 11.99872655),
('C', 12.31249807),
('B', 12.48817861),
('E', 12.49693343),
('A', 12.74087388),
('D', 12.95688859)]
As #jonrsharpe pointed out, the variable name isn't a property of those values, so you'll have to attach it differently. I think the easiest way is to go about it like this:
my_array = [[12.74087388, 'A'], [12.48817861, 'B'], etc]
my_sorted_array = sorted(my_array)
my_sorted_named_array = [i[1] for i in my_sorted_array]
This is a dictionary-based solution, as suggested in the comments.
lst = [12.74087388, 12.48817861, 12.31249807, 12.95688859,
12.49693343, 11.51090636, 10.16505019, 11.99872655]
d = dict(zip(list('ABCDEFGH'), lst))
sorted_names = list(zip(*sorted(d.items(), key=lambda x: x[1])))[0]
# ('G', 'F', 'H', 'C', 'B', 'E', 'A', 'D')
I suppose you prefer a list of tuples instead of a dictionary in case you have duplicated letters.
data = [
('A', 12.74087388),
('B', 12.48817861),
('C', 12.31249807),
('D', 12.95688859),
('E', 12.49693343),
('F', 11.51090636),
('G', 10.16505019),
('H', 11.99872655)
]
dt = np.dtype([('letter', np.unicode_, 1), ('num', np.float64)])
arr = np.array(data, dtype=dt)
arr.sort(order='num')

Combinations between one element of each list of combinations [duplicate]

This question already has answers here:
How to get the cartesian product of multiple lists
(17 answers)
Closed 6 years ago.
I have about 12 lists [a, b, c, ... , z] with arbitrary elements and i´ve got a series of combinations through itertools.combinations(iterable, n) resulting in lists of combinations that match each of the original list.
The great deal now is to get a list with all the possible combinations, picking one element(combination) of each combinations list.
One simplified exemple would be:
A = [a,b,c]
B = [d,e,f]
C = [g,h,i]
my_iterable = [A, B, C]
And the output should be:
>>> foo(my_iterable)
(a,d,g), (a,d,h), (a,d,i), (a,e,g), (a,e,h), ... , (c,f,i)
The input iterables, e.g. 'A, B & C', may have variable lengths and foo() may be a generator function.
A = ['a','b','c']
B = ['d','e','f']
C = ['g','h','i']
l = [(a, b, c) for a in A for b in B for c in C]
print(l)
out:
[('a', 'd', 'g'), ('a', 'd', 'h'), ('a', 'd', 'i'), ('a', 'e', 'g'), ('a', 'e', 'h'), ('a', 'e', 'i'), ('a', 'f', 'g'), ('a', 'f', 'h'), ('a', 'f', 'i'), ('b', 'd', 'g'), ('b', 'd', 'h'), ('b', 'd', 'i'), ('b', 'e', 'g'), ('b', 'e', 'h'), ('b', 'e', 'i'), ('b', 'f', 'g'), ('b', 'f', 'h'), ('b', 'f', 'i'), ('c', 'd', 'g'), ('c', 'd', 'h'), ('c', 'd', 'i'), ('c', 'e', 'g'), ('c', 'e', 'h'), ('c', 'e', 'i'), ('c', 'f', 'g'), ('c', 'f', 'h'), ('c', 'f', 'i')]

Zip lists of tuples

I'm doing some stuff with data from files, and I have already zipped every column with its info, but now i want to combine info from other files (where i have zipped the info too) and i don't know how to unzip and get it together.
EDIT:
I have a couple of zip objects:
l1 = [('a', 'b'), ('c', 'd')] # list(zippedl1)
l2 = [('e', 'f'), ('g', 'h')] # list(zippedl1)
l3 = [('i', 'j'), ('k', 'm')] # list(zippedl1)
and i want to unzip like:
unzipped = [('a', 'c', 'e', 'g', 'i', 'k'), ('b', 'd', 'f', 'h', 'j', 'm')]
I wouldn't like to transform the zipped structures to a list, just for memory reasons. I searched and i didn't find something that helps me. Hope you can help me please!.
[sorry about my bad english]
I believe you want to zip an unpacked chain:
# Leaving these as zip objects as per your edit
l1 = zip(('a', 'c'), ('b', 'd'))
l2 = zip(('e', 'g'), ('f', 'h'))
l3 = zip(('i', 'k'), ('j', 'm'))
unzipped = [('a', 'c', 'e', 'g', 'i', 'k'), ('b', 'd', 'f', 'h', 'j', 'm')]
You can simply do
from itertools import chain
result = list(zip(*chain(l1, l2, l3)))
# You can also skip list creation if all you need to do is iterate over result:
# for x in zip(chain(l1, l2, l3)):
# print(x)
print(result)
print(result == unzipped)
This prints:
[('a', 'c', 'e', 'g', 'i', 'k'), ('b', 'd', 'f', 'h', 'j', 'm')]
True
You need to concatenate the lists first:
>>> l1 = [('a', 'b'), ('c', 'd')]
>>> l2 = [('e', 'f'), ('g', 'h')]
>>> l3 = [('i', 'j'), ('k', 'm')]
>>> zip(*(l1 + l2 + l3))
[('a', 'c', 'e', 'g', 'i', 'k'), ('b', 'd', 'f', 'h', 'j', 'm')]

Trying to turn inner and out tuples into inner and outer lists

Ok, so I've got information in the form of
(('A', 'B', 'C'), ('D', 'E', 'F'), ('H', 'I', 'J'))
and I would like to convert this to
[['A', 'B', 'C'], ['D', 'E', 'F'], ['H', 'I', 'J']]
What is the best/easiest way to do this?
List comprehension:
tpl = (('A', 'B', 'C'), ('D', 'E', 'F'), ('H', 'I', 'J'))
lst = [list(x) for x in tpl]
a = (('A', 'B', 'C'), ('D', 'E', 'F'), ('H', 'I', 'J'))
print map(list, a)
prints
[['A', 'B', 'C'], ['D', 'E', 'F'], ['H', 'I', 'J']]
>>> data = (('A', 'B', 'C'), ('D', 'E', 'F'), ('H', 'I', 'J'))
>>> [list(tup) for tup in data]
[['A', 'B', 'C'], ['D', 'E', 'F'], ['H', 'I', 'J']]
Here is a simple recursive solution for any number of nested tuples:
>>> tup = (('A', ('B', 'C')), ('D', 'E', 'F', ('H', 'I', 'J')))
>>> listify = lambda x: map(listify, x) if isinstance(x, tuple) else x
>>> listify(tup)
[['A', ['B', 'C']], ['D', 'E', 'F', ['H', 'I', 'J']]]
For Python 3 replace map(listify, x) with list(map(listify, x)).
If you know the structure is only two levels, try:
x = (('A', 'B', 'C'), ('D', 'E', 'F'), ('H', 'I', 'J'))
y = [ list(t) for t in x ]
If there might be deeper nesting, you'll want recursion -- see F.J's answer.

Categories