I have two lists:
list1=[0,0,0,1,1,2,2,3,3,4,4,5,5,5]
list2=['a','b','c','d','e','f','k','o','n','q','t','z','w','l']
dictionary=dict(zip(list1,list2))
I would like to output values of the same keys in one for each key such as it will print like this:
0 ['a','b','c']
1 ['d','e']
2 ['f','k']
3 ['o','n']
4 ['q','t']
5 ['z','w','l']
I wrote following code to do that but it does not work as I think
for k,v in dictionary.items():
print (k,v)
Could you tell me how to fix code so that I can get above intended results, please ?
Thanks in advance!
Regarding your code:
dictionary = dict(zip(list1, list2))
creates the dictionary:
{0: 'c', 1: 'e', 2: 'k', 3: 'n', 4: 't', 5: 'l'}
which loses all but the last value in each group. You need to process the zipped lists to construct the grouped data. Two ways are with itertools.groupby() or with a defaultdict(list), shown here.
Use a collections.defaultdict of lists to group the items with keys from list1 and values from list2. Pair the items from each list with zip():
from collections import defaultdict
list1=[0,0,0,1,1,2,2,3,3,4,4,5,5,5]
list2=['a','b','c','d','e','f','k','o','n','q','t','z','w','l']
d = defaultdict(list)
for k,v in zip(list1, list2):
d[k].append(v)
for k in sorted(d):
print('{} {!r}'.format(k, d[k]))
Output:
0 ['a', 'b', 'c']
1 ['d', 'e']
2 ['f', 'k']
3 ['o', 'n']
4 ['q', 't']
5 ['z', 'w', 'l']
Since items in a dictionary are unordered, the output is sorted by key.
The code you've shown does not look anything like what you described.
That aside, you can group values of the same key together by first zipping the lists and then grouping values of the same key using a collections.defaultdict:
from collections import defaultdict
d = defaultdict(list)
for k, v in zip(list1, list2):
d[k].append(v)
print(d)
# defaultdict(<type 'list'>, {0: ['a', 'b', 'c'], 1: ['d', 'e'], 2: ['f', 'k'], 3: ['o', 'n'], 4: ['q', 't'], 5: ['z', 'w', 'l']})
You can use itertool.groupby for a concise, one line solution:
import itertools
list1=[0,0,0,1,1,2,2,3,3,4,4,5,5,5]
list2=['a','b','c','d','e','f','k','o','n','q','t','z','w','l']
final_list = {a:[i[-1] for i in list(b)] for a, b in itertools.groupby(zip(list1, list2), key=lambda x: x[0])}
for a, b in final_list.items():
print(a, b)
Output:
0 ['a', 'b', 'c']
1 ['d', 'e']
2 ['f', 'k']
3 ['o', 'n']
4 ['q', 't']
5 ['z', 'w', 'l']
Related
I have a list that was used to create a new list of lists (sub_lst1) and I want to use that sub_list1 to filter the remaining values in the list.
And use those remaining values to create a new list of lists (sub_lst2).
I have provided a toy example below of the problem.
I have tried the following:
lst = ['f','f','a','g','h','a','b','g','h','a','h','d','a','b']
sub_lst1 = []
sub_lst2 = []
>>> for i, v in enumerate(lst):
... if "b" in v:
... sub_lst1.append(lst[i-3:i+1])
>>>print(sub_lst1)
[['g', 'h', 'a', 'b'], ['h', 'd', 'a', 'b']]
>>> for i, v in enumerate(lst):
... if sub_lst1[0:][0:] not in v:
... sub_lst2.append(lst[i-2:i+1])
>>> print(sub_lst2)
[[], [], ['f', 'f', 'a'],['f', 'a', 'g'], ['a', 'g', 'h'], ['g', 'h', 'a'], ['a', 'b', 'g'], ['b', 'g', 'h'], ['g', 'h', 'a'], ['h', 'a', 'h'], ['a', 'h', 'd'], ['h', 'd', 'a']]
But the desired result would be to have the two sub-lists where one sub-list has the two preceding values to 'a' and 'b' and the second sub-list has the two preceding values of 'a' where 'b' does not follow 'a'. The sub-lists would look as follows:
>>> print(sub_lst1)
[['g', 'h', 'a', 'b'], ['h', 'd', 'a', 'b']]
>>> print(sub_lst2)
[['f', 'f', 'a'], ['g', 'h', 'a']]
I'd recommend tackling this problem by simply finding where the 'b's are and then slicing up the main list in one go, rather than doing it in two steps. For example:
lst = ['f','f','a','g','h','a','b','g','h','a','h','d','a','b']
sub_lst1 = []
sub_lst2 = []
to_find = 'b'
found_indexes = []
for i, v in enumerate(lst):
if v == to_find:
found_indexes.append(i)
last_idx = -1
for idx in found_indexes:
sub_lst2.append(lst[last_idx+1:idx-3])
sub_lst1.append(lst[idx-3:idx+1])
last_idx = idx
if lst[-1] != to_find: # don't forget to check in case 'b' isn't the last entry
sub_lst2.append(lst[last_idx+1:])
This gets the result you are looking for, assuming that if 'b' isn't the last entry, you would want sub_lst2 to include the trailing letters.
I'm sure there's a solution with superior speed that involves turning the first lst into a single string of characters and then split()ing it using 'b', but I don't think speed is your concern and this answer will work for a list with contents of any type, not just single characters.
I have 2 lists
in1=[1,1,1,2,2,3,4,4,4,5,5]
in2=['a','b','c','d','e','f','g','h','i','j','k']
I want to group the second list based on the same elements in the first list i.e.
Output has to be
out=[['a','b','c'],['d','e'],['f'],['g','h','i'],['j','k']]
Explanation: the first 3 elements of the first list are the same, so I want the first 3 elements of the 2nd list to be grouped together (and so on)
If anyone can help out, it would be great!
~Thanks
Just zip the lists, then itertools to the rescue.
from itertools import groupby
in1 = [1,1,1,2,2,3,4,4,4,5,5]
in2 = ['a','b','c','d','e','f','g','h','i','j','k']
result = [[c for _, c in g] for _, g in groupby(zip(in1, in2), key=lambda x: x[0])]
print(result)
# [['a', 'b', 'c'], ['d', 'e'], ['f'], ['g', 'h', 'i'], ['j', 'k']]
Non-itertools solution:
in1 = [1,1,1,2,2,3,4,4,4,5,5]
in2 = ['a','b','c','d','e','f','g','h','i','j','k']
result = [[]]
key = in1[0]
for k, v in zip(in1, in2):
if k != key:
result.append([])
key = k
result[-1].append(v)
print(result)
# [['a', 'b', 'c'], ['d', 'e'], ['f'], ['g', 'h', 'i'], ['j', 'k']]
I have a list of lists like so: N = [[a,b,c],[d,e,f],[g,h,i]]
I would like to create a dictionary of all the first values of each list inside N so that I have;
d = {1:[a,d,g],2:[b,e,h],3:[c,f,i]}
I have tried many things and I cant figure it out. The closest I have gotten:
d = {}
for i in range(len(N)):
count = 0
for j in N[i]:
d[count] = j
count+=1
But this doesnt give me the right dictionary? I would really appreciate any guidance on this, thank you.
You can use a dict comprehension (I use N with 4 items, to avoid confusion):
N=[['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'],['w', 'j', 'l']]
{i+1:[k[i] for k in N] for i in range(len(N[0]))}
#{1: ['a', 'd', 'g', 'w'], 2: ['b', 'e', 'h', 'j'], 3: ['c', 'f', 'i', 'l']}
You can transpose the list with zip(*N) and then use enumerate to get the index and the elements into pairs for dict.
>>> dict((i+1, list(j)) for i, j in enumerate(zip(*N)))
{1: ['a', 'd', 'g'], 2: ['b', 'e', 'h'], 3: ['c', 'f', 'i']}
Alternate based on suggestion by #Vishal Singh
>> dict((i, list(j)) for i, j in enumerate(zip(*N), start=1))
Check the provided code below and output.
N = [[a,b,c],[d,e,f],[g,h,i]]
d = {}
for y in range(0,len(N)):
tmp=[]
for x in N:
tmp.append(x[y])
d[y+1]=tmp
//Output:
{1: [a, d, g], 2: [b, e, h], 3: [c, f, i]}
Hope that helps!
Here is a simple solution. Just pass your list to this function.
def list_to_dict(lis):
a=0
lis2=[]
dict={}
n=len(lis)
while a<n:
for el in lis:
lis2.append(el[a])
dict[a+1]=lis2
lis2=[]
a+=1
return dict
my_list=[["a","b","c"],["d","e","f"],["g","h","i"]]
print(list_to_dict(my_list))
I have two lists:
a= [0,0,0,1,1,1,3,3,3]
b= ['a','b','c','d','e','f','g','h','i']
output = [['a','b','c'],['d','e','f'],['g','h','i']]
a and b are list of same length.
I need an output array by in such a way that whenever the value in list - a changes from 0 to 1 or from 1 to 3, A new list should be made in the output list.
can someone please help.
Use groupby:
from itertools import groupby
from operator import itemgetter
a = [0, 0, 0, 1, 1, 1, 3, 3, 3]
b = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
output = [list(map(itemgetter(1), group)) for _, group in groupby(zip(a, b), key=itemgetter(0))]
print(output)
Output
[['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
A simpler method without using any imports by utilizing dictionary:
a= [0,0,0,1,1,1,3,3,3]
b= ['a','b','c','d','e','f','g','h','i']
d = {e: [] for e in set(a)} # Create a dictionary for each of a's unique key
[d[e].append(b[i]) for i, e in enumerate(a)] # put stuff into lists by index
lofl = list(d.values())
>>> lofl
[['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
Using groupby, you could do:
from itertools import groupby
a= [0,0,0,1,1,1,3,3,3]
b= ['a','b','c','d','e','f','g','h','i']
iter_b = iter(b)
output = [[next(iter_b) for _ in group] for key, group in groupby(a)]
print(output)
# [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
groupby yields successive groups of identical values of a. For each group, we create a list containing as many of the next elements of b as there are values in the group.
As you added tag algorithm , I believe you want a solution without so many magic.
>>> def merge_lists(A, B):
... output = []
... sub_list = []
... current = A[0]
... for i in range(len(A)):
... if A[i] == current:
... sub_list.append(B[i])
... else:
... output.append(sub_list)
... sub_list = []
... sub_list.append(B[i])
... current = A[i]
... output.append(sub_list)
... return output
...
>>> a= [0,0,0,1,1,1,3,3,3]
>>> b= ['a','b','c','d','e','f','g','h','i']
>>> merge_list(a, b)
[['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
I have two lists:
A = ['T', 'D', 'Q', 'D', 'D']
sessionid = [1, 1, 1, 2, 2]
Is there anyway i could group items in A for the same sessionid, so that i could print out the following:
1: ["T", "D","Q"]
2: ["D","D"]
The itertools groupby function is designed to do this sort of thing. Some of the other answers here create a dictionary, which is very sensible, but if you don't actually want a dict then you can do this:
from itertools import groupby
from operator import itemgetter
A = ['T', 'D', 'Q', 'D', 'D']
sessionid = [1, 1, 1, 2, 2]
for k, g in groupby(zip(sessionid, A), itemgetter(0)):
print('{}: {}'.format(k, list(list(zip(*g))[1])))
output
1: ['T', 'D', 'Q']
2: ['D', 'D']
operator.itemgetter(0) returns a callable that fetches the item at index 0 of whatever object you pass it; groupby uses this as the key function to determine what items can be grouped together.
Note that this and similar solutions assume that the sessionid indices are sorted. If they aren't then you need to sort the list of tuples returned by zip(sessionid, A) with the same key function before passing them to groupby.
edited to work correctly on Python 2 and Python 3
Not using itertools, you can use a dictionary:
index = 0
dict = {}
for i in sessionid:
if not (i in dict):
dict[i] = []
else:
dict[i].append(A[index])
index += 1
print(dict) # {1: ['T', 'D', 'Q'], 2: ['D', 'D']}
And based on the remarks below:
from collections import defaultdict
dict = defaultdict(list)
for i, item in enumerate(sessionid):
dict[item].append(A[i])
You could use a dictionary and zip:
A = ['T', 'D', 'Q', 'D', 'D']
sessionid = [1, 1, 1, 2, 2]
result = {i:[] for i in sessionid}
for i,j in zip(sessionid,A):
result[i].append(j)
Or you can use defaultdict:
from collections import defaultdict
result = defaultdict(list)
for k, v in zip(sessionid, A):
result[k].append(v)
Output:
>>> result
{1: ['T', 'D', 'Q'], 2: ['D', 'D']}
One liner
{k: list(i for (i, _) in v) for k, v in itertools.groupby(zip(A, sessionid), operator.itemgetter(1))}
Without nested loop
{k: list(map(operator.itemgetter(0), v)) for k, v in itertools.groupby(zip(A, sessionid), operator.itemgetter(1))}
You can do:
import pandas as pd
A = ['T', 'D', 'Q', 'D', 'D']
sessionid = [1, 1, 1, 2, 2]
pd.DataFrame({'A':A, 'id':sessionid}).groupby('id')['A'].apply(list).to_dict()
#Out[10]: {1: ['T', 'D', 'Q'], 2: ['D', 'D']}
You could also convert them into numpy arrays, and use the indices of the session ids you need with np.where
import numpy as np
A = np.asarray(['T', 'D', 'Q', 'D', 'D'])
sessionid = np.asarray([1, 1, 1, 2, 2])
Ind_1 = np.where(sessionid == 1)
Ind_2 = np.where(sessionid == 2)
print A[Ind_1]
should return ['T' 'D' 'Q']
you could of course turn this into a function which takes N, the desired session and returns your A values.
Hope this helps!