my_list = ['c1','c2','c3']
Is there anyway to create a certain amount of new lists based on items inside of a list?
Result would be:
c1 = []
c2 = []
c3 = []
You can do that using globals():
>>> my_list = ['c1','c2','c3']
>>> for x in my_list:
... globals()[x] = []
...
>>> c1
[]
>>> c2
[]
>>> c3
[]
But it's better to use a dict here:
>>> dic = {item : [] for item in my_list}
>>> dic
{'c2': [], 'c3': [], 'c1': []}
Instead of creating new global variables using the names from your list, I would suggest using a dictionary:
my_list = ['c1', 'c2', 'c3']
my_dict = {k: [] for k in my_list}
Then to access one of those lists you could use something like my_dict['c1'] or my_dict['c2'].
Another solution would be to add the new lists as attributes to some object or module. For example:
lists = type('Lists', (object,), {k: [] for k in my_list})
After which you could access your lists using lists.c1, lists.c2, etc.
In my opinion both of these methods are cleaner than modifying globals() or locals() and they give you very similar behavior.
Note that if you are on Python 2.6 or below you will need to replace the dictionary comprehensions with dict((k, []) for k in my_list).
Related
list1 = [[1,2,3],[4,5,6]]
list2 = ['a','b','c']
list3 = ['A','B']
main_list = [{k: dict(zip(list2, sub))} for k,sub in zip(list3, list1)]
print(main_list)
I am trying to work on this code, my goal is to write a dictionary within a nested dictionary. So, basically I'm trying to add the content in the main_list inside an empty dictionary. I'm hoping to get this ouput shown below:
{{'A':{'a':1, 'b':2, 'c':3}, {'B':{'a':4, 'b':5, 'c',6}}}
Please help:(
I think I found a solution:
main_dict = {k: v for i, k in enumerate(list3) for v in [{c: n for c, n in zip(list2, list1[i])}]}
I would not call it 'main_list', given it's a dict.
This question already has answers here:
Create a dictionary with comprehension
(17 answers)
Closed 5 years ago.
I am looking for a short and compact one-liner to initialize a dictionary from a list in Python. Is there an equivalent to the two constructs below?
dic = {}
for elt in list:
dic[elt.hash] = elt
.
dic2 = {}
defaultValue = 0
for elt in list:
dic2[elt] = defaultValue
I've see the use of Counter for the second case, but it is a very narrow case, and I'm looking for a generic syntax.
Summary of three pythonic solutions to instantiating dictionaries. Having a "one-line" solution should never be the most important consideration.
1. Keys and default value defined in advance.
Instead of setting a default value for every key, use dict.fromkeys. Also, do not name variables the same as classes, e.g. use lst instead.
dic2 = dict.fromkeys(lst, 0)
2. Default value defined in advance, but not keys.
Alternatively, if you will be adding more keys in the future, consider using collections.defaultdict, which is a subclass of dict:
from collections import defaultdict
dic2 = defaultdict(int)
dic2['newkey'] # returns 0 even not explicitly set
3. Keys and values related by a function.
For building a dictionary where keys and values are linked via a function, use a dictionary comprehension, as described in detail by #OmerB, e.g.
{k: f(k) for k in lst} # value function of given keys
{f(v): v for v in lst} # key function of given values
Well, dictionary comprehension is one-line, is that what you mean?
>> MyList = ['apple', 'banana', 'pear']
>> {hash(element): element for element in MyList}
{-8723846192743330971: 'pear',
-6060554681585566095: 'banana',
-4133088065282473265: 'apple'}
Also - I'm suspecting that using the element's hash as the key is not what you're looking for:
If your elements are immutable (e.g. strings), you could use the elements themselves as keys.
If they're not immutable, you can use the element's location in the list.
For the latter, to make sure you insert each value only once to the dict, clear duplicates from the list before iterating over it:
>> MyList = ['apple', 'apple', 'banana', 'banana', 'pear']
>> {idx: value for (idx,value) in enumerate(set(MyList))}
{0: 'banana', 1: 'pear', 2: 'apple'}
A simple one liner statement for case-01 using dict constructor, map and zip:
>>> l = ['a','b','c']
>>> dict(zip(map(hash,l),l))
>>> {12416037344: 'a', 12672038114: 'c', 12544037731: 'b'}
For second situation:
>>> l = ['a','b','c']
>>> default_value = 10
>>> dict((zip(l,[default_value]*len(l))))
>>> {'a': 10, 'c': 10, 'b': 10}
Those two constructs can be built using dictionary comprehensions like:
Code:
dic_comp = {getattr(elt, 'hash'): elt for elt in test_data}
dic2_comp = {elt: defaultValue for elt in test_data}
Test Code:
class TestObj(object):
def __init__(self, hash_value):
self.hash = hash_value
test_data = [TestObj(i) for i in range(5)]
dic = {}
for elt in test_data:
dic[elt.hash] = elt
dic_comp = {getattr(elt, 'hash'): elt for elt in test_data}
assert dic == dic_comp
dic2 = {}
defaultValue = 0
for elt in test_data:
dic2[elt] = defaultValue
dic2_comp = {elt: defaultValue for elt in test_data}
assert dic2 == dic2_comp
My attempt to programmatically create a dictionary of lists is failing to allow me to individually address dictionary keys. Whenever I create the dictionary of lists and try to append to one key, all of them are updated. Here's a very simple test case:
data = {}
data = data.fromkeys(range(2),[])
data[1].append('hello')
print data
Actual result: {0: ['hello'], 1: ['hello']}
Expected result: {0: [], 1: ['hello']}
Here's what works
data = {0:[],1:[]}
data[1].append('hello')
print data
Actual and Expected Result: {0: [], 1: ['hello']}
Why is the fromkeys method not working as expected?
When [] is passed as the second argument to dict.fromkeys(), all values in the resulting dict will be the same list object.
In Python 2.7 or above, use a dict comprehension instead:
data = {k: [] for k in range(2)}
In earlier versions of Python, there is no dict comprehension, but a list comprehension can be passed to the dict constructor instead:
data = dict([(k, []) for k in range(2)])
In 2.4-2.6, it is also possible to pass a generator expression to dict, and the surrounding parentheses can be dropped:
data = dict((k, []) for k in range(2))
Try using a defaultdict instead:
from collections import defaultdict
data = defaultdict(list)
data[1].append('hello')
This way, the keys don't need to be initialized with empty lists ahead of time. The defaultdict() object instead calls the factory function given to it, every time a key is accessed that doesn't exist yet. So, in this example, attempting to access data[1] triggers data[1] = list() internally, giving that key a new empty list as its value.
The original code with .fromkeys shares one (mutable) list. Similarly,
alist = [1]
data = dict.fromkeys(range(2), alist)
alist.append(2)
print(data)
would output {0: [1, 2], 1: [1, 2]}. This is called out in the dict.fromkeys() documentation:
All of the values refer to just a single instance, so it generally doesn’t make sense for value to be a mutable object such as an empty list.
Another option is to use the dict.setdefault() method, which retrieves the value for a key after first checking it exists and setting a default if it doesn't. .append can then be called on the result:
data = {}
data.setdefault(1, []).append('hello')
Finally, to create a dictionary from a list of known keys and a given "template" list (where each value should start with the same elements, but be a distinct list), use a dictionary comprehension and copy the initial list:
alist = [1]
data = {key: alist[:] for key in range(2)}
Here, alist[:] creates a shallow copy of alist, and this is done separately for each value. See How do I clone a list so that it doesn't change unexpectedly after assignment? for more techniques for copying the list.
You could use a dict comprehension:
>>> keys = ['a','b','c']
>>> value = [0, 0]
>>> {key: list(value) for key in keys}
{'a': [0, 0], 'b': [0, 0], 'c': [0, 0]}
This answer is here to explain this behavior to anyone flummoxed by the results they get of trying to instantiate a dict with fromkeys() with a mutable default value in that dict.
Consider:
#Python 3.4.3 (default, Nov 17 2016, 01:08:31)
# start by validating that different variables pointing to an
# empty mutable are indeed different references.
>>> l1 = []
>>> l2 = []
>>> id(l1)
140150323815176
>>> id(l2)
140150324024968
so any change to l1 will not affect l2 and vice versa.
this would be true for any mutable so far, including a dict.
# create a new dict from an iterable of keys
>>> dict1 = dict.fromkeys(['a', 'b', 'c'], [])
>>> dict1
{'c': [], 'b': [], 'a': []}
this can be a handy function.
here we are assigning to each key a default value which also happens to be an empty list.
# the dict has its own id.
>>> id(dict1)
140150327601160
# but look at the ids of the values.
>>> id(dict1['a'])
140150323816328
>>> id(dict1['b'])
140150323816328
>>> id(dict1['c'])
140150323816328
Indeed they are all using the same ref!
A change to one is a change to all, since they are in fact the same object!
>>> dict1['a'].append('apples')
>>> dict1
{'c': ['apples'], 'b': ['apples'], 'a': ['apples']}
>>> id(dict1['a'])
>>> 140150323816328
>>> id(dict1['b'])
140150323816328
>>> id(dict1['c'])
140150323816328
for many, this was not what was intended!
Now let's try it with making an explicit copy of the list being used as a the default value.
>>> empty_list = []
>>> id(empty_list)
140150324169864
and now create a dict with a copy of empty_list.
>>> dict2 = dict.fromkeys(['a', 'b', 'c'], empty_list[:])
>>> id(dict2)
140150323831432
>>> id(dict2['a'])
140150327184328
>>> id(dict2['b'])
140150327184328
>>> id(dict2['c'])
140150327184328
>>> dict2['a'].append('apples')
>>> dict2
{'c': ['apples'], 'b': ['apples'], 'a': ['apples']}
Still no joy!
I hear someone shout, it's because I used an empty list!
>>> not_empty_list = [0]
>>> dict3 = dict.fromkeys(['a', 'b', 'c'], not_empty_list[:])
>>> dict3
{'c': [0], 'b': [0], 'a': [0]}
>>> dict3['a'].append('apples')
>>> dict3
{'c': [0, 'apples'], 'b': [0, 'apples'], 'a': [0, 'apples']}
The default behavior of fromkeys() is to assign None to the value.
>>> dict4 = dict.fromkeys(['a', 'b', 'c'])
>>> dict4
{'c': None, 'b': None, 'a': None}
>>> id(dict4['a'])
9901984
>>> id(dict4['b'])
9901984
>>> id(dict4['c'])
9901984
Indeed, all of the values are the same (and the only!) None.
Now, let's iterate, in one of a myriad number of ways, through the dict and change the value.
>>> for k, _ in dict4.items():
... dict4[k] = []
>>> dict4
{'c': [], 'b': [], 'a': []}
Hmm. Looks the same as before!
>>> id(dict4['a'])
140150318876488
>>> id(dict4['b'])
140150324122824
>>> id(dict4['c'])
140150294277576
>>> dict4['a'].append('apples')
>>> dict4
>>> {'c': [], 'b': [], 'a': ['apples']}
But they are indeed different []s, which was in this case the intended result.
You can use this:
l = ['a', 'b', 'c']
d = dict((k, [0, 0]) for k in l)
You are populating your dictionaries with references to a single list so when you update it, the update is reflected across all the references. Try a dictionary comprehension instead. See
Create a dictionary with list comprehension in Python
d = {k : v for k in blah blah blah}
You could use this:
data[:1] = ['hello']
I have a prototype dictionary that i want to use as a basis for appending to a list.
I want to change 1 or more values in the dictionary then capture it as an element of a list.
My question is this; is there any other recommended method for doing this short of using deepcopy().
I know this doesn't work properly:
l = []
d = {}
d['key'] = 4
l.append(d)
d['key'] = 5
l.append(d)
it gives:
l = [{'key': 5}, {'key': 5}]
it also didn't seem to work using a simply copy()
You are appending a reference to the same object to both lists, so when you change the value of "key", you change it in both lists. You need to make a copy of the dictionary before appending if you want a separate reference, using the dict.copy function:
l = []
d = {}
d['key'] = 4
l.append(d.copy())
d['key'] = 5
l.append(d.copy())
If you need a deep copy, you can use the copy library:
import copy
l = []
d = {}
d['key'] = 4
l.append(copy.deepcopy(d))
d['key'] = 5
l.append(copy.deepcopy(d))
copy should work.
l = []
d = {}
d['key'] = 4
l.append(d)
d = d.copy()
d['key'] = 5
l.append(d)
Result:
[{'key': 4}, {'key': 5}]
This question already has answers here:
How can I make a dictionary (dict) from separate lists of keys and values?
(21 answers)
Closed 7 months ago.
I have these lists:
list1 = ["a","b","c"]
list2 = ["1","2","3"]
I need to add them to a dictionary, where list1 is the key and list2 is the value.
I wrote this code:
d = {}
for i in list1:
for j in list2:
d[i] = j
print d
The output is this:
{'a':'3','b':'3','c':'3'}
What's wrong with this code? How can I write it so the output is
{'a':'1','b':'2','c':'3'}
Thanks!
Zip the lists and use a dict comprehension :
{i: j for i, j in zip(a, b)}
Or, even easier, just use dict() :
dict(zip(a, b))
You should keep it simple, so the last solution is the best, but I kept the dict comprehension example to show how it could be done.
you are almost there, except you need to iterate over the lists simultaneously
In [1]: list1 = ["a","b","c"]
In [2]: list2 = ["1","2","3"]
In [3]: d = {}
In [4]: for i, j in zip(list1, list2):
...: d[i] = j
...:
In [5]: print d
{'a': '1', 'c': '3', 'b': '2'}
You can also use dict comprehension to do the following in a nice one-liner.
d = {i : j for i, j in zip(list1, list2)}
list1 = ["a","b","c"]
list2 = ["1","2","3"]
mydict = {}
for i,j in zip(list1,list2):
mydict[i] = j
print mydict