How to make a dictionary from two nested list? - python

I have two nested lists:
list1 = [['s0'], ['s1'], ['s2']]
list2 = [['hello','world','the'],['as','per','the'],['assets','order']]
and I want to make a dictionary from these lists with keys from list1 and values from list2:
d = {s0:['hello','world','the'],s1:['as','per','the'],s2:['assets','order']}
The output should look like this:
d = {s0:['hello','world','the'],s1:['as','per','the'],s2:['assets','order']}
The following code works if list1 is a normal (non-nested) list. But it doesn't work when list1 is a nested list.
dict(zip(list1, list2))

The problem here is that lists are not hashable, so one thing you can do is to flatten your list with itertools.chain and then build the dictionary with strings (which are immutable) as keys following you're current approach (read here for a more detailed explanation on this topic):
from itertools import chain
dict(zip(chain.from_iterable(list1),list2))
{'s0': ['hello', 'world', 'the'],
's1': ['as', 'per', 'the'],
's2': ['assets', 'order']}

If you want to do it manually (to understand algorithm for exemple), here is a way to do so:
list1 = [['s0'], ['s1'], ['s2']]
list2 = [['hello','world','the'],['as','per','the'],['assets','order']]
if len(list1) != len(list2):
exit(-1)
res = {}
for index, content in enumerate(list1):
res[content[0]] = list2[index]
print(res)

Another answer could be :
list1 = [['s0'], ['s1'], ['s2']]
list2 = [['hello','world','the'],['as','per','the'],['assets','order']]
output_dict = {element1[0]: element2 for element1, element2 in zip(list1, list2)}
An similar way of this dict-comprehension :
output_dict = {element1: element2 for [element1], element2 in zip(list1, list2)}
Output :
{'s0': ['hello', 'world', 'the'],
's1': ['as', 'per', 'the'],
's2': ['assets', 'order']}

It's a strange way to store matching information in the first place, but I would combine them like this:
list1 = [['s0'], ['s1'], ['s2']]
list2 = [['hello','world','the'],['as','per','the'],['assets','order']]
assert(len(list1) == len(list2))
output_dict = dict()
for index in range(len(list1)):
output_dict[list1[index][0] = list2[index]
result:
{'s0': ['hello', 'world', 'the'], 's1': ['as', 'per', 'the'], 's2': ['assets', 'order']}
I am assuming that the variables s0, s1 and s2 are meant to be strings like in the first list.

Related

How to extract the last sub-list from a list of lists?

If I have a list of lists, how can I remove every element from each list, except for the last element? (Keeping only the last element from each list and deleting all other elements before it)
If my list of lists looks like this:
lst = [['Hello', 'World'], ['Hello', 'E', 'Planet'], ['Planet', 'World', 'Earth']]
I want my outputted list to look like this:
lst_new = [['World'], ['Planet'], ['Earth']]
So far, my code looks like this, but the problem I'm facing is that it is eliminating the last list entirely from the list of lists:
lst_new = [x for x in lst if x != lst.remove(lst[len(lst)-1])]
print(lst_new)
#[['Hello', 'World'], ['Hello', 'E', 'Planet']]
Where am I going wrong? Would appreciate any help - thanks!
Just use simple indexing:
>>> lst_new = [ [x[-1]] for x in lst ]
>>> lst_new
[['World'], ['Planet'], ['Earth']]
You can use slicing:
lst = [['Hello', 'World'], ['Hello', 'E', 'Planet'], ['Planet', 'World', 'Earth']]
lst_new = [sublst[-1:] for sublst in lst]
print(lst_new) # [['World'], ['Planet'], ['Earth']]

Search string value from a list with dictionary list values

Below I have a list and dict with the values as below. The dict has keys associated with list values.
What I wanted was to search strings in the list with values of the list in the dictionary and with each match capture the corresponding key value and create a new list with the key values for each match as above listed.
list = ['man', 'men', 'boy', 'buoy', 'cat','caat']
dict={'man':['man', 'men', 'mun'], 'boy':['boy','buoy','bay'], 'cat':['cat','caat','cut']}
Expected output for above case is:
Outputlist=['man','man','boy','boy','cat','cat']
When I tried the same I am getting only one item to match as below.
lis = ['man', 'men', 'boy', 'buoy', 'cat','caat']
dic={'man':['man', 'men', 'mun'], 'boy':['boy','buoy','bay'], 'cat':['cat','caat','cut']}
for key,value in dic.items():
if value in lis:
output.append(key)
print(output)
you can use a nested list comprehension. Notice that you should not use list and dict as variables:
x = [key for key, value in dict_.items() for x in list_ if x in value]
print(x) # ['man', 'man', 'boy', 'boy', 'cat', 'cat']
The first thing to note is that to achieve the same length input and output lists, you should be looping over the list, not the dictionary.
ys = [k for x in xs for k, v in d.items() if x in v]
Another way is to construct a reverse mapping. This should make things asymptotically faster:
lookup = {x: k for k, v in d.items() for x in v}
>>> lookup
{
'bay': 'boy',
'boy': 'boy',
'buoy': 'boy',
'caat': 'cat',
'cat': 'cat',
'cut': 'cat',
'man': 'man',
'men': 'man',
'mun': 'man',
}
Then, simply:
ys = [lookup[x] for x in xs]
I think you did it the wrong way. First, you wan to go across the lis and after find the corresponding key :
output = []
lis = ['man', 'men', 'boy', 'buoy', 'cat','caat']
dic={'man':['man', 'men', 'mun'], 'boy':['boy','buoy','bay'], 'cat':['cat','caat','cut']}
for l in lis:
for key, value in dic.items():
if l in value:
output.append(key)
print(output)
As the others mention, you can use list comprehension to do it directly:
output = [next(k for k,v in dict if l in v) for l in list]

List of Lists to Dictionary of Lists

I am having a hard time converting a list of lists to a dictionary of lists due to some of the key values being the same, I am also getting an issue with the null value. My List is:
L = [['shark', ['one']], ['shark',['two']], ['fish', ['one']], ['fish', ['two']], ['fish',[]]]
My desired dictionary of lists would be structured like this:
Dic = {'shark': ['one','two'], 'fish':['one', 'two', '0']}
Is there any trick to be able to get the same key values to combine into a dictionary of lists like this?
L = [['shark', ['one']], ['shark',['two']], ['fish', ['one']], ['fish', ['two']], ['fish',[]]]
p = {}
for k, v in L:
d = p.setdefault(k, [])
if not v:v = ['0']
d.extend(v)
print p
output:
{'shark': ['one', 'two'], 'fish': ['one', 'two', '0']}
from collections import defaultdict
dct = defaultdict(list)
l = [['shark', ['one']], ['shark',['two']], ['fish', ['one']], ['fish', ['two']], ['fish',[]]]
for x in l:
dct[x[0]].append(x[1])
dct
>>> defaultdict(list,
{'fish': [['one'], ['two'], []], 'shark': [['one'], ['two']]})
if you need '0' instead of [] then add an if clause to the loop

Multi-list comprehension

Given the following data structure, how would I get the max length of the characters inside it?
data = [['a', 'b'], ['cc', 'dd']]
The largest item is 'cc' so the answer would be 2. Here is what I have so far, but it is incorrect.
max_chars = [len(item) for item for item in data]
This should do it
max_chars = max(len(item) for lst in data for item in lst)
I dislike nested list comprehensions. They're hard to read.
Using itertools, you can flatten the data and then find the max length.
import itertools
flat = itertools.chain(*data)
result = max(len(i) for i in flat)
Note that flat is an iterable object that's difficult to inspect, but list(flat) returns ['a', 'b', 'cc', 'dd']
Max takes a key function:
>>> max([['a', 'b'], ['cc', 'dd']], key=lambda l: max(len(e) for e in l))
['cc', 'dd']
>>> max([['a', 'bbb'], ['cc', 'dd']], key=lambda l: max(len(e) for e in l))
['a', 'bbb']
That prints the sublist with the longest element. If you want the value of the length and the index of the individual sublist, you could do:
>>> data=[['a', 'bbb'], ['cc', 'dd']]
>>> maxes=((i, len(max(l, key=len))) for i, l in enumerate(data))
>>> max(maxes, key=lambda t:t[1])
(0, 3) # first element is the sublist index, second the length

How to check if list1 contains some elements of list2?

I need to remove few strings from the list1 so i put them into list2 and just cant find out how to make it works.
list1 = ['abc', 'def', '123']
list2 = ['def', 'xyz', 'abc'] # stuff to delete from list1
And I would like to remove 'abc' and 'def' from list1 so it only contains things that i need
You can do this by using list comprehension as a filter, like this
set2, list1 = set(['def', 'xyz', 'abc']), ['abc', 'def', '123']
print [item for item in list1 if item not in set2]
# ['123']
We convert the elements of list2 to a set, because they offer faster lookups.
The logic is similar to writing like this
result = []
for item in list1:
if item not in set2:
result.append(item)
If you don't have any duplicate in list1 (or if you want to remove duplicates), you can use this:
list1 = set(['abc', 'def', '123'])
list2 = set(['def', 'xyz', 'abc'])
print(list(list1 - list2))
list1 = set(['abc', 'def', '123'])
list2 = set(['def', 'xyz', 'abc'])
# here result will contain only the intersected element
# so its very less.
result = set(filter(set(list1).__contains__, list2))
newlist = list()
for elm in list1:
if elm not in result:
newlist.append(elm)
print newlist
Output:
['123']
An even shorter answer using builtin set methods:
list1 = ['abc', 'def', '123']
list2 = ['def', 'xyz', 'abc']
set1 = set(list1)
set2 = set(list2)
print(set1.difference(set2)))
Quote from above documentation:
"Return a new set with elements in the set that are not in the others."

Categories

Resources