Create dictionary from splitted strings from list of strings - python

I feel that this is very simple and I'm close to solution, but I got stacked, and can't find suggestion in the Internet.
I have list that looks like:
my_list = ['name1#1111', 'name2#2222', 'name3#3333']
In general, each element of the list has the form: namex#some_number.
I want to make dictionary in pretty way, that has key = namex and value = some_number. I can do it by:
md = {}
for item in arguments:
md[item.split('#')[0]] = item.split('#')[1]
But I would like to do it in one line, with list comprehension or something. I tried do following, and I think I'm not far from what I want.
md2 = dict( (k,v) for k,v in item.split('#') for item in arguments )
However, I'm getting error: ValueError: too many values to unpack. No idea how to get out of this.

You actually don't need the extra step of creating the tuple
>>> my_list = ['name1#1111', 'name2#2222', 'name3#3333']
>>> dict(i.split('#') for i in my_list)
{'name3': '3333', 'name1': '1111', 'name2': '2222'}

Related

Given two list of words, than return as dictionary and set together

Hey (Sorry bad english) so am going to try and make my question more clear. if i have a function let's say create_username_dict(name_list, username_list). which takes in two list's 1 being the name_list with names of people than the other list being usernames that is made out of the names of people. what i want to do is take does two list than convert them to a dictonary and set them together.
like this:
>>> name_list = ["Ola Nordmann", "Kari Olsen", "Roger Jensen"]
>>> username_list = ["alejon", "carli", "hanri"]
>>> create_username_dict(name_list, username_list)
{
"Albert Jones": "alejon",
"Carlos Lion": "carli",
"Hanna Richardo": "hanri"
}
i have tried look around on how to connect two different list in too one dictonary, but can't seem to find the right solution
If both lists are in matching order, i.e. the i-th element of one list corresponds to the i-th element of the other, then you can use this
D = dict(zip(name_list, username_list))
Use zip to pair the list.
d = {key: value for key,value in zip(name_list, username_list)}
print(d)
Output:
{'Ola Nordmann': 'alejon', 'Kari Olsen': 'carli', 'Roger Jensen': 'hanri'}
Considering both the list are same length and one to one mapping
name_list = ["Ola Nordmann", "Kari Olsen", "Roger Jensen"]
username_list = ["alejon", "carli", "hanri"]
result_stackoverflow = dict()
for index, name in enumerate(name_list):
result_stackoverflow[name] = username_list[index]
print(result_stackoverflow)
>>> {'Ola Nordmann': 'alejon', 'Kari Olsen': 'carli', 'Roger Jensen': 'hanri'}
Answer by #alex does the same but maybe too encapsulated for a beginner. So this is the verbose version.

Separate elements divided by comma in a list

I have a list of strings that contains elements of the type
List=['name1,vol', 'name1,price','name2, vol', 'name2,price'.... ]
I would like to extract a list only of "names" which are the parts that actually change as the second components in each element have a fix pattern (here:vol, price). Notice that the "names" can obviously have different length. To sum up, I'd like to extract something like:
List_names=['name1', 'name2' ]
How can I do that?
What if I have something of the type:
List_tricky=[('name1', 'vol'), ('name1', 'price'),('name2', 'vol'), ('name2', 'price').... ]
Something like this?
List=['name1,vol', 'name1,price','name2, vol', 'name2,price']
names = []
for string in List:
name = string.split(',')[0]
names.append(name)
print(names)
For your 'tricky' case, you can try:
# initialize variables:
names = []
# iterate over each point (tuple):
for point in List:
# get name:
name = point[0]
# append to list:
names.append(name)
print(names)
You could turn it into a dict then back into a list using str.split. (No loop required as it does it efficiently for you) Use functools.partial to apply the split to each string instead of a lambda:
from functools import partial
list(dict(map(partial(str.split, sep=','), List)))
This works for either input but way more simple for the list of tuples:
>>> l = ['name1,vol', 'name1,price','name2, vol', 'name2,price'.... ]
>>> list(dict(map(partial(str.split, sep=','), List)))
['name1', 'name2']
>>> l = [('name1', 'vol'), ('name1', 'price'),('name2', 'vol'), ('name2', 'price').... ]
>>> list(dict(l))
['name1', 'name2']
Similar logic to #Daniel Sokol's answer , you can use a one liner :
list2 = [x.split(',')[0] for x in List]
To add on top of #Alireza Tajadod's already wonderful answer, you might want to apply conversion to a set, then back to a list to remove any possible duplication items, as suggested by #Cryptoharf84 in the comments.
names_list = list(set([entry.split(',')[0] for entry in List]))
The same logic with list comprehension can be applied to the trickier case.
names_list_2 = list(set([entry[0] for entry in List_tricky]))
To make list comprehension more explicit, you can also do the following:
names_list_3 = list(set([name for name, _ in List_tricky]))
The _ indicates that we are discarding the second value of the unpacked tuple.
Sets are useful because converting a list with duplicate elements into a set effectively removes any duplications.
As a tip, look for naming conventions in python. But never name variables starting with upper case, nor with existing class names.
I will try something like:
list_names = [s.split(',')[0].strip() for s in List]
list_unique_names(set(list_names))
split returns a list of "chunks" of the original string, and strip to remove whitespaces on beginning/end of the resulting string.
I will change your data structure to dict instead of list
d={'name1': ('vol', 'price'),'name2': ('vol', 'price'), .... }
In order to get just the names:
d.keys()
You can also use a .map() function:
# Case 1: List
all_names = map(lambda x :a.split(',')[0], List)
# Case 2: List_tricky
all_names = [i[0] for i in List_tricky]
# After the code is the same
unique_names = set(all_names)
List_names = list(unique_names)
print(List_names)

How to convert a list of tuples containing two lists into dictionary of key value pairs?

I have a list like this-
send_recv_pairs = [(['produce_send'], ['consume_recv']), (['Send'], ['Recv']), (['sender2'], ['receiver2'])]
I want something like
[ {['produce_send']:['consume_recv']},{['Send']:['Recv']},{['sender2']:['receiver2']}
How to do this?
You can not use list as the key of dictionary.
This Article explain the concept,
https://wiki.python.org/moin/DictionaryKeys
To be used as a dictionary key, an object must support the hash function (e.g. through hash), equality comparison (e.g. through eq or cmp), and must satisfy the correctness condition above.
And
lists do not provide a valid hash method.
>>> d = {['a']: 1}
TypeError: unhashable type: 'list'
If you want to specifically differentiate the key values you can use tuple as they hash able
{ (i[0][0], ): (i[1][0], ) for i in send_recv_pairs}
{('Send',): ('Recv',),
('produce_send',): ('consume_recv',),
('sender2',): ('receiver2',)}
You can't have lists as keys, only hashable types - strings, numbers, None and such.
If you still want to use a dictionary knowing that, then:
d={}
for tup in send_recv_pairs:
d[tup[0][0]]=tup[1]
If you want the value to be string as well, use tup[1][0] instead of tup[1]
As a one liner:
d={tup[0][0]]:tup[1] for tup in list} #tup[1][0] if you want values as strings
You can check it over here, in the second way of creating distionary.
https://developmentality.wordpress.com/2012/03/30/three-ways-of-creating-dictionaries-in-python/
A Simple way of doing it,
First of all, your tuple is tuple of lists, so better change it to tuple of strings (It makes more sense I guess)
Anyway simple way of working with your current tuple list can be like :
mydict = {}
for i in send_recv_pairs:
print i
mydict[i[0][0]]= i[1][0]
As others pointed out, you cannot use list as key to dictionary. So the term i[0][0] first takes the first element from the tuple - which is a list- and then the first element of list, which is the only element anyway for you.
Do you mean like this?
send_recv_pairs = [(['produce_send'], ['consume_recv']),
(['Send'], ['Recv']),
(['sender2'], ['receiver2'])]
send_recv_dict = {e[0][0]: e[1][0] for e in send_recv_pairs}
Resulting in...
>>> {'produce_send': 'consume_recv', 'Send': 'Recv', 'sender2': 'receiver2'}
As mentioned in other answers, you cannot use a list as a dictionary key as it is not hashable (see links in other answers).
You can therefore just use the values in your lists (assuming they stay as simple as in your example) to create the following two possibilities:
send_recv_pairs = [(['produce_send'], ['consume_recv']), (['Send'], ['Recv']), (['sender2'], ['receiver2'])]
result1 = {}
for t in send_recv_pairs:
result1[t[0][0]] = t[1]
# without any lists
result2 = {}
for t in send_recv_pairs:
result2[t[0][0]] = t[1][0]
Which respectively gives:
>>> result1
{'produce_send': ['consume_recv'], 'Send': ['Recv'], 'sender2': ['receiver2']}
>>> result2
{'produce_send': 'consume_recv', 'Send': 'Recv', 'sender2': 'receiver2'}
Try like this:
res = { x[0]: x[1] for x in pairs } # or x[0][0]: x[1][0] if you wanna store inner values without list-wrapper
It's for Python 3 and when keys are unique. If you need collect list of values per key, instead of single value, than you may use something like itertools.groupby or map+reduce. Wrote about this in comments and I'll provide example.
And yes, list cannot store key-values, only dict's, but maybe it's just typo in question.
You can not use list as the dictionary key, but instead you may type-cast it as tuple to create the dict object.
Below is the sample example using a dictionary comprehension:
>>> send_recv_pairs = [(['produce_send'], ['consume_recv']), (['Send'], ['Recv']), (['sender2'], ['receiver2'])]
>>> {tuple(k): v for k, v in send_recv_pairs}
{('sender2',): ['receiver2'], ('produce_send',): ['consume_recv'], ('Send',): ['Recv']}
For details, take a look at: Why can't I use a list as a dict key in python?
However if your nested tuple pairs were not list, but any other hashable object pairs, you may have type-casted it to dict for getting the desired result. For example:
>>> my_list = [('key1', 'value1'), ('key2', 'value2')]
>>> dict(my_list)
{'key1': 'value1', 'key2': 'value2'}

How do I make a list with the same name as a dictionary key?

I have a dictionary, containing several hundred entries, of format:
>>>dict
{'1620': 'aaaaaa'}
I would like to make new empty lists named '1620', etc. I have tried variations of the following but it doesn't recognize eachkey as a variable to be used when creating the list. Instead, it names the list literally "eachkey" and my key, in this example '1620', is not connected to the new list.
>>>for eachkey in dict.keys():
>>> eachkey=[]
>>>
>>>eachkey
[]
>>>'1620'
1620
Edited to add:
Maybe I could make the list at the same time as I make the dictionary? Slip it in here below? The str(eachfile[-4:]) is what I want the list named.
files=open(sys.argv[1])
dict={}
for eachfile in files:
value=open(eachfile)
key=str(eachfile[-4:])
dict[key]=value
eachfile.close()
Edit: it would be fine for me to add letters along w/ the numbers if that's what it needs.
I don't think it's possible to change the integer literal 1620 so that it gives you an object other than the integer 1620. Similarly I don't think you can change the string literal '1620' to give you a list instead of a string.
You could do it if you prefix the variable names with some letters to make them valid names. For example you could use my1620 instead of 1620. I wouldn't advise doing this, but it's possible:
>>> d = {'1620': 'aaaaaa'}
>>> for k,v in d.items():
... locals()['my'+k] = []
>>> my1620
'aaaaaa'
With a dict like this:
d1 = {'foo':'bar', '1621':'hello'}
Try doing this:
d2 = dict((k,list()) for k in d1.keys())
Now d2 is:
{'1621': [], 'foo': []}
And you can reference your lists list so:
d2['1621'].append(20)
d2['foo'].append(5)
d2['foo'].append('zig')
Which makes d2:
{'1621': [20], 'foo': [5, 'zig']}
As Gareth said, it's VERY unlikely you really want to do what you're asking to do. This is probably better.

Most efficient way to add new keys or append to old keys in a dictionary during iteration in Python?

Here's a common situation when compiling data in dictionaries from different sources:
Say you have a dictionary that stores lists of things, such as things I like:
likes = {
'colors': ['blue','red','purple'],
'foods': ['apples', 'oranges']
}
and a second dictionary with some related values in it:
favorites = {
'colors':'yellow',
'desserts':'ice cream'
}
You then want to iterate over the "favorites" object and either append the items in that object to the list with the appropriate key in the "likes" dictionary or add a new key to it with the value being a list containing the value in "favorites".
There are several ways to do this:
for key in favorites:
if key in likes:
likes[key].append(favorites[key])
else:
likes[key] = list(favorites[key])
or
for key in favorites:
try:
likes[key].append(favorites[key])
except KeyError:
likes[key] = list(favorites[key])
And many more as well...
I generally use the first syntax because it feels more pythonic, but if there are other, better ways, I'd love to know what they are. Thanks!
Use collections.defaultdict, where the default value is a new list instance.
>>> import collections
>>> mydict = collections.defaultdict(list)
In this way calling .append(...) will always succeed, because in case of a non-existing key append will be called on a fresh empty list.
You can instantiate the defaultdict with a previously generated list, in case you get the dict likes from another source, like so:
>>> mydict = collections.defaultdict(list, likes)
Note that using list as the default_factory attribute of a defaultdict is also discussed as an example in the documentation.
Use collections.defaultdict:
import collections
likes = collections.defaultdict(list)
for key, value in favorites.items():
likes[key].append(value)
defaultdict takes a single argument, a factory for creating values for unknown keys on demand. list is a such a function, it creates empty lists.
And iterating over .items() will save you from using the key to get the value.
Except defaultdict, the regular dict offers one possibility (that might look a bit strange): dict.setdefault(k[, d]):
for key, val in favorites.iteritems():
likes.setdefault(key, []).append(val)
Thank you for the +20 in rep -- I went from 1989 to 2009 in 30 seconds. Let's remember it is 20 years since the Wall fell in Europe..
>>> from collections import defaultdict
>>> d = defaultdict(list, likes)
>>> d
defaultdict(<class 'list'>, {'colors': ['blue', 'red', 'purple'], 'foods': ['apples', 'oranges']})
>>> for i, j in favorites.items():
d[i].append(j)
>>> d
defaultdict(<class 'list'>, {'desserts': ['ice cream'], 'colors': ['blue', 'red', 'purple', 'yellow'], 'foods': ['apples', 'oranges']})
All of the answers are defaultdict, but I'm not sure that's the best way to go about it. Giving out defaultdict to code that expects a dict can be bad. (See: How do I make a defaultdict safe for unexpecting clients? ) I'm personally torn on the matter. (I actually found this question looking for an answer to "which is better, dict.get() or defaultdict") Someone in the other thread said that you don't want a defaultdict if you don't want this behavior all the time, and that might be true. Maybe using defaultdict for the convenience is the wrong way to go about it. I think there are two needs being conflated here:
"I want a dict whose default values are empty lists." to which defaultdict(list) is the correct solution.
and
"I want to append to the list at this key if it exists and create a list if it does not exist." to which my_dict.get('foo', []) with append() is the answer.
What do you guys think?

Categories

Resources