Appending nested list values into a new list - python

I've got a program that has a nested list which I wish to access and then append to a new list based on a condition. There are three columns in each list and I wish to know how to access them individually. Here's how it looks currently [['A', 'B', 'C'], ['D', 'E', 'F'], ['G', 'H', 'I']]. An example to better explain this would be, if I wanted data from the second column my new list would then look like ['B', 'E', 'H'].
This is what I have so far but I'm currently rather stuck..
n = 0
old_list = [['A', 'B', 'C'], ['D', 'E', 'F'], ['G', 'H', 'I']]
new_list = []
for a, sublist in enumerate(old_list):
for b, column in enumerate(sublist):
print (a, b, old_list[a][b])
if n == 0:
new_list.append(column[0])
if n == 1:
new_list.append(column[1])
if n == 2:
new_list.append(column[2])
print(new_list)
My current output..
0 0 A
0 1 B
0 2 C
1 0 D
1 1 E
1 2 F
2 0 G
2 1 H
2 2 I
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']
My desired output ..
n = 0
new_list = ['A', 'D', 'G']
n = 1
new_list = ['B', 'E', 'H']
n = 2
new_list = ['C', 'F', 'I']
Thanks for your help!

>>> L = [['A', 'B', 'C'], ['D', 'E', 'F'], ['G', 'H', 'I']]
>>> columns = list(zip(*L))
>>> columns
[('A', 'D', 'G'), ('B', 'E', 'H'), ('C', 'F', 'I')]
>>> columns[1] # 2nd column
('B', 'E', 'H')
Or if you want each column as a list to modify(since zip returns immutable tuples) then use:
columns = [list(col) for col in zip(*L)]

Another solution, which does not use the * construction nor zip():
for n in range(3):
print('n = {}'.format(n))
new_list = [sublist[n] for sublist in old_list]
print('new_list = {}'.format(new_list))

Related

Combination of pair elements within list in a list

I'm trying to obtain the combinations of each element in a list within a list. Given this case:
my_list
[['A', 'B'], ['C', 'D', 'E'], ['F', 'G', 'H', 'I']]
The output would be:
0
1
0
A
B
1
C
D
2
C
E
3
D
E
4
F
G
5
F
H
6
F
I
7
G
H
8
G
I
9
H
I
Or it could also be a new list instead of a DataFrame:
my_new_list
[['A','B'], ['C','D'], ['C','E'],['D','E'], ['F','G'],['F','H'],['F','I'],['G','H'],['G','I'],['H','I']]
This should do it. You have to flatten the result of combinations.
from itertools import combinations
x = [['A', 'B'], ['C', 'D', 'E'], ['F', 'G', 'H', 'I']]
y = [list(combinations(xx, 2)) for xx in x]
z = [list(item) for subl in y for item in subl]
z
[['A', 'B'],
['C', 'D'],
['C', 'E'],
['D', 'E'],
['F', 'G'],
['F', 'H'],
['F', 'I'],
['G', 'H'],
['G', 'I'],
['H', 'I']]
Create combination by itertools.combinations with flatten values in list comprehension:
from itertools import combinations
L = [['A', 'B'], ['C', 'D', 'E'], ['F', 'G', 'H', 'I']]
data = [list(j) for i in L for j in combinations(i, 2)]
print (data)
[['A', 'B'], ['C', 'D'], ['C', 'E'],
['D', 'E'], ['F', 'G'], ['F', 'H'],
['F', 'I'], ['G', 'H'], ['G', 'I'],
['H', 'I']]
And then pass to DataFrame by constructor:
df = pd.DataFrame(data)
print (df)
0 1
0 A B
1 C D
2 C E
3 D E
4 F G
5 F H
6 F I
7 G H
8 G I
9 H I
def get_pair( arrs ):
result = []
for arr in arrs:
for i in range(0, len(arr) - 1 ):
for j in range( i + 1, len(arr) ):
result.append( [arr[i], arr[j]] )
return result
arrs = [['A', 'B'], ['C', 'D', 'E'], ['F', 'G', 'H', 'I']]
print( get_pair(arrs) )

Combining elements in a list of list based on having common elements

I have a list of lists like so
list=[[a], [b], [c], [d],[e],[f], [a,f], [b,c], [c,e], [b, d,f]]
note that it includes singles and combinations.
What I would like to do is to iterate the list so that a new list of every possible combination of these sub-components is appended to the list of lists if and only if they share at least one common entry.
so the product is as follows
list2=[[a], [b], [c], [d],[e],[f], [a,f], [b,c], [c,e], [b, d,f], **[b,c,e], [a,b,d,f], [b,c,d,f], [b,c,d,e,f], [a,b,c,d,e,f]]**
Note the new part of the list contains the original list of lists
def similar(x):
prev_l = 0
while prev_l != len(x):
to_add = []
prev_l = len(x)
for i in x:
if len(i) == 1:
continue
for j in x:
if len(j) == 1:
continue
if any([_ in j for _ in i]) and not any([set(i+j) == set(_) for _ in x]) and not any([set(i+j) == set(_) for _ in to_add]) and i != j:
to_add.append(list(set(i+j)))
x += to_add
return x
Input:
>>> l = [['a'], ['b'], ['c'], ['d'],['e'],['f'], ['a','f'], ['b','c'], ['c','e'], ['b', 'd','f']]
>>> similar(l)
Output:
>>> l
[['a'], ['b'], ['c'], ['d'], ['e'], ['f'], ['a', 'f'], ['b', 'c'], ['c', 'e'], ['b', 'd', 'f'], ['b', 'a', 'd', 'f'], ['b', 'e', 'c'], ['b', 'd', 'c', 'f'], ['b', 'a', 'f', 'd', 'c'], ['b', 'f', 'e', 'd', 'c'], ['b', 'a', 'f', 'e', 'd', 'c']]
I should note this has O(n^3) in worst case. If you're using this for something floyd warshall I wouldn't be too worried as that has O(n^3) anyway, but if not you should definitely populate a distance matrix and then look for adjacency in that.

How to split a list and into a tuple

If i have a list
lst = ['a', 'k', 'b', 'c', 'k', 'd', 'e', 'g']
and I want to split into new list without 'k', and turn it into a tuple. So I get
(['a'],['b', 'c'], ['d', 'e', 'g'])
I am thinking about first splitting them into different list by using a for loop.
new_lst = []
for element in lst:
if element != 'k':
new_ist.append(element)
This does remove all the 'k' but they are all together. I do not know how to split them into different list. To turn a list into a tuple I would need to make a list inside a list
a = [['a'],['b', 'c'], ['d', 'e', 'g']]
tuple(a) == (['a'], ['b', 'c'], ['d', 'e', 'g'])
True
So the question would be how to split the list into a list with sublist.
You are close. You can append to another list called sublist and if you find a k append sublist to new_list:
lst = ['a', 'k', 'b', 'c', 'k', 'd', 'e', 'g']
new_lst = []
sublist = []
for element in lst:
if element != 'k':
sublist.append(element)
else:
new_lst.append(sublist)
sublist = []
if sublist: # add the last sublist
new_lst.append(sublist)
result = tuple(new_lst)
print(result)
# (['a'], ['b', 'c'], ['d', 'e', 'g'])
If you're feeling adventurous, you can also use groupby. The idea is to group elements as "k" or "non-k" and use groupby on that property:
from itertools import groupby
lst = ['a', 'k', 'b', 'c', 'k', 'd', 'e', 'g']
result = tuple(list(gp) for is_k, gp in groupby(lst, "k".__eq__) if not is_k)
print(result)
# (['a'], ['b', 'c'], ['d', 'e', 'g'])
Thanks #YakymPirozhenko for the simpler generator expression
tuple(list(i) for i in ''.join(lst).split('k'))
Output:
(['a'], ['b', 'c'], ['d', 'e', 'g'])
Here's a different approach, using re.split from the re module, and map:
import re
lst = ['a', 'k', 'b', 'c', 'k', 'd', 'e', 'g']
tuple(map(list, re.split('k',''.join(lst))))
(['a'], ['b', 'c'], ['d', 'e', 'g'])
smallerlist = [l.split(',') for l in ','.join(lst).split('k')]
print(smallerlist)
Outputs
[['a', ''], ['', 'b', 'c', ''], ['', 'd', 'e', 'g']]
Then you could check if each sub lists contain ''
smallerlist = [' '.join(l).split() for l in smallerlist]
print(smallerlist)
Outputs
[['a'], ['b', 'c'], ['d', 'e', 'g']]
How about slicing, without appending and joining .
def isplit_list(lst, v):
while True:
try:
end = lst.index(v)
except ValueError:
break
yield lst[:end]
lst = lst[end+1:]
if len(lst):
yield lst
lst = ['a', 'k', 'b', 'c', 'k', 'd', 'e', 'g', 'k']
results = tuple(isplit_list(lst, 'k'))
Try this, works and doesn't need any imports!
>>> l = ['a', 'k', 'b', 'c', 'k', 'd', 'e', 'g']
>>> t = []
>>> for s in ''.join(l).split('k'):
... t.append(list(s))
...
>>> t
[['a'], ['b', 'c'], ['d', 'e', 'g']]
>>> t = tuple(t)
>>> t
(['a'], ['b', 'c'], ['d', 'e', 'g'])
Why don't you make a method which will take a list as an argument and return a tuple like so.
>>> def list_to_tuple(l):
... t = []
... for s in l:
... t.append(list(s))
... return tuple(t)
...
>>> l = ['a', 'k', 'b', 'c', 'k', 'd', 'e', 'g']
>>> l = ''.join(l).split('k')
>>> l = list_to_tuple(l)
>>> l
(['a'], ['b', 'c'], ['d', 'e', 'g'])
Another approach using itertools
import more_itertools
lst = ['a', 'k', 'b', 'c', 'k', 'd', 'e', 'g']
print(tuple(more_itertools.split_at(lst, lambda x: x == 'k')))
gives
(['a'], ['b', 'c'], ['d', 'e', 'g'])

How to create list of lists from flat list in python [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I have a list:
l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
Is there a way to create a list of lists so that:
l = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
And would it be possible to create the list of lists where the lists are of different sizes? For example:
l = [['a', 'b'], ['c', 'd', 'e', 'f'], ['g'], ['h', 'i']]
1 . For a multi-dimensioned list of defined inner list size :
>>> inner_size = 3
>>> out = [ l[i:i+inner_size] for i in range(0, len(l), inner_size) ]
>>> out
=> [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
2 . For a multi-dimensioned list of random inner list size (this is kind of chunky unfortunately) :
>>> import random
>>> i=0
>>> out = []
>>> while i<len(l):
left_out = len(l) - i
inner_size = random.randint(1,left_out)
out.append(l[i: i+inner_size])
i += inner_size
>>> out
=> [['a'], ['b'], ['c', 'd', 'e', 'f', 'g'], ['h', 'i']]
For a consistent chunk size n, you can do:
l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
n = 3
l2 = [l[i:i + n] for i in range(0, len(l), n)]
l2
# [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
Given split indexes (which you can easily generate from a list of chunk sizes), you can produce custom slices:
splits = [0, 2, 6, 7, 9]
l2 = [l[start:end] for start, end in zip(splits, splits[1:])]
l2
# [['a', 'b'], ['c', 'd', 'e', 'f'], ['g'], ['h', 'i']]
Here is a simple solution, you can set your own chunk sizes in the variable chunk_sizes either as a list or tuple or an integer
def chunk_list(l,chunk_sizes):
if isinstance(chunk_sizes,int):
for i in range(0,len(l),chunk_sizes):
yield l[i:i + chunk_sizes]
else:
start = 0
for size in chunk_sizes:
if start < len(l):
yield l[start:start + size]
start += size
l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
# custom chunk_sizes list
chunk_sizes = [2,4,1,2]
print ([sl for sl in chunk_list(l,chunk_sizes)])
#prints [['a', 'b'], ['c', 'd', 'e', 'f'], ['g'], ['h', 'i']]
# integer chunk_sizes
chunk_sizes = 3
print ([sl for sl in chunk_list(l,chunk_sizes)])
#prints [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]

Switch first and last elements of two lists in Python

In Python, I have two lists that either have equal number of elements (e.g. 8 and 8) or one less than the other (e.g. 7 and 8; 3 and 4):
list1 = ['A', 'B', 'C', 'D']
list2 = ['E', 'F', 'G', 'H']
or
list3 = ['A', 'B', 'C']
list4 = ['D', 'E', 'F', 'G']
I'm trying to figure out the best way to build an algorithm that will switch the last half of the first list with the first half of the last list, resulting in this, when both lists have an even number of elements:
switched_list1 = ['A', 'B', 'E', 'F']
switched_list2 = ['C', 'D', 'G', 'H']
…and this when the one of the lists has an odd number:
switched_list3 = ['A', 'D', 'E']
switched_list4 = ['B', 'C', 'F', 'G']
What's the most efficient way to build an algorithm that can switch list elements like this?
list1 = ['A', 'B', 'C']
list2 = ['D', 'E', 'F', 'G']
nlist1 = len(list1)/2
nlist2 = len(list2)/2
new1 = list1[:nlist1] + list2[:nlist2]
new2 = list1[nlist1:] + list2[nlist2:]
print new1
print new2
produces
['A', 'D', 'E']
['B', 'C', 'F', 'G']
>>> def StrangeSwitch(list1,list2):
return (list1[:len(list1)/2]+list2[:len(list2)/2],list1[len(list1)/2:]+list2[len(list2)/2:])
>>> list1 = ['A', 'B', 'C', 'D']
>>> list2 = ['E', 'F', 'G', 'H']
>>> (list1,list2)=StrangeSwitch(list1,list2)
>>> list1
['A', 'B', 'E', 'F']
>>> list2
['C', 'D', 'G', 'H']
>>> list3 = ['A', 'B', 'C']
>>> list4 = ['D', 'E', 'F', 'G']
>>> (list3,list4)=StrangeSwitch(list3,list4)
>>> list3
['A', 'B', 'C']
>>> list4
['B', 'C', 'F', 'G']
>>>
Reading the Comments by OP I would take the priviledge of proposing another approach
>>> def StrangeSwitchFast(list1,list2):
#return (list1[:len(list1)/2]+list2[:len(list2)/2],list1[len(list1)/2:]+list2[len(list2)/2:])
return (list(itertools.chain(itertools.islice(list1,0,len(list1)/2),itertools.islice(list2,0,len(list2)/2))),
list(itertools.chain(itertools.islice(list1,len(list1)/2,None),itertools.islice(list2,len(list2)/2,None))))
The above doesn't create any temporary list and if OP desires to use it as an iterator rather than a list for the downstream processing, then the list can be safely dropped from the function and can be left to return as a tuple of iterators.

Categories

Resources