how join list tuple and dict into a dict? - python

how join list tuple and dict into a dict?
['f','b','c','d'] (1,2,3) and {'a':'10'}
d excluded for list be compatible with the tuple
output {'f':'1','b':'2','c':'3','a':'10'}

You can make a dict from keys and values like so:
keys = ['a','b','c','d']
values = (1,2,3)
result = dict(zip(keys, values)) # {'a': 1, 'c': 3, 'b': 2}
Then you can update it with another dict
result.update({ 'f' : 5 })
print result # {'a': 1, 'c': 3, 'b': 2, 'f': 5}

dict(zip(a_list, a_tuple)).update(a_dictionary)
when a_list is your list, a_tuple is your tuple and a_dictionary is your dictionary.
EDIT:
If you really wanted to turn the numbers in you tuple into strings than first do:
new_tuple = tuple((str(i) for i in a_tuple))
and pass new_tuple to the zip function.

This will accomplish the first part of your question:
dict(zip(['a','b','c','d'], (1,2,3)))
However, the second part of your question would require a second definition of 'a', which the dictionary type does not allow. However, you can always set additional keys manually:
>>> d = {}
>>> d['e'] = 10
>>> d
{'e':10}

The keys in a dictionary must be unique, so this part: {'a':'1','a':'10'} is impossible.
Here is code for the rest:
l = ['a','b','c','d']
t = (1,2,3)
d = {}
for key, value in zip(l, t):
d[key] = value

Something like this?
>>> dict({'a':'10'}.items() + (zip(['f','b','c','d'],('1','2','3'))))
{'a': '10', 'c': '3', 'b': '2', 'f': '1'}

Since noone has given an answer that converts the tuple items to str yet
>>> L=['f','b','c','d']
>>> T=(1,2,3)
>>> D={'a':'10'}
>>> dict(zip(L,map(str,T)),**D)
{'a': '10', 'c': '3', 'b': '2', 'f': '1'}

>>> l = ['a','b','c','d']
>>> t = (1,2,3)
>>> d = {'a':'10'}
>>> t = map(str, t) # the OP has requested str values, let's do this first
If you are OK with mutating the original dict, then you can just do this:
>>> d.update(zip(l, t))
or in Python 3.9+ (PEP 584):
>>> d |= zip(l, t)
But if you need to keep the original d intact:
>>> new_d = dict(zip(l, t))
>>> new_d |= d

Related

Appending to dictionary in a loop [duplicate]

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']

int values in dict appending as list

I have a for loop which is going through multiple dictionaries and adding the values under common keys. The input dictionary has keys that are strings and values that are int's. For some reason its adding the values as lists of one value (e.g. {"01":[12],[44]}). I want it to add the int on its own but cant get that working for some reason. I'm using the code below, is there something i am missing ?
dw = defaultdict()
dw = {}
for key, value in listb.items():
dw[key].append(value)
If you want to forgo all good practice and not use defaultdict(list), you can use setdefault and call it every single time you choose to add a value. This is inefficient and not idiomatic, but it will work.
In [1]: from collections import defaultdict
In [2]: a = defaultdict(list)
In [3]: b = {}
In [4]: a[1].append(1)
In [5]: b.setdefault(1, []).append(1)
In [6]: a
Out[6]: defaultdict(list, {1: [1]})
In [7]: b
Out[7]: {1: [1]}
In [8]:
As long as the values in the dicts are ints (not lists):
dw = {}
for key, value in listb.items():
try: # Key exists in dictionary and value is a list
dw[key].append(value)
except KeyError: # Key does not yet exist in dictionary
dw[key] = value
except AttributeError: # Key exist in dictionary and value is not a list
dw[key] = [dw[key], value]
If you mean to add key/value pairs to the dictionary (and not append to an array), it's:
for key, value in listb.items():
dw[key] = value
EDIT: or is it something like this you're after?
listb = {'1': 3, '2': 5}
dw = {'1': 5, '2': 9}
for key, value in listb.items():
if key not in dw.keys():
dw[key] = []
else:
dw[key] = [dw[key]]
dw[key].append(value)
which gives dw = {'2': [9, 5], '1': [5, 3]}
If you have a list like listb = [{'a': 1, 'b': 2}, {'a': 3, 'b': 4, 'c': 5}, {'b': 1}], you can try this:
dw = {}
for d in listb:
for k, v in d.items():
if k in dw:
if isinstance(dw[k], list):
dw[k].append(v)
elif isinstance(dw[k], int):
dw[k] = [dw[k], v]
else:
dw[k] = v
print(dw)
{'a': [1, 3], 'b': [2, 4, 1], 'c': 5}
>>>

How do I swap two random values from a dictionary?

I need to swap two random values from a dicitonary
def alphabetcreator():
letters = random.sample(range(97,123), 26)
newalpha = []
engalpha =['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
alphasmerged = {}
for i in letters:
newalpha.append(chr(i))
alphasmerged = dict(zip(engalpha, newalpha))
return(alphabetsmerged)
This code gives me my two different alphabets, putting them into a dictionary so I can translate between one and the other. I now need to randomly swap two of the values whilst keeping all the rest the same. How can I do this?
You can first use random.sample to randomly pick two different values from a collection.
From the doc:
Return a k length list of unique elements chosen from the population sequence or set. Used for random sampling without replacement.
Use this function on the keys of your dictionary to have two distinct keys.
In Python 3, you can directly use it on a dict_keys object.
In Python 2, you can either convert d.keys() into a list, or directly pass the dictionary to the sample.
>>> import random
>>> d = {'a': 1, 'b': 2}
>>> k1, k2 = random.sample(d.keys(), 2) # Python 3
>>> k1, k2 = random.sample(d, 2) # Python 2
>>> k1, k2
['a', 'b']
Then, you can in-place-ly swap two values of a collection.
>>> d[k1], d[k2] = d[k2], d[k1]
>>> d
{'b': 1, 'a': 2}
d = {12: 34, 67: 89}
k, v = random.choice(list(d.items()))
d[v] = k
d.pop(k)
which when running, gave the random output of d as:
{12: 34, 89: 67}
You can try this:
import random
engalpha =['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
new_dict = {a:b for a, b in zip(engalpha, map(chr, random.sample(range(97,123), 26)))}
key_val = random.choice(list(new_dict.keys()))
final_dict = {b if a == key_val else a:a if a == key_val else b for a, b in new_dict.items()}
Regarding your recent comment:
import random
s = {'a': 'h', 'b': 'd', 'c': 'y'}
random_dict = [(a, b) for a, b in random.sample(list(s.items()), 2)]
new_dict = {a:b for a, b in zip([i[0] for i in sorted(random_dict, key=lambda x:x[0])], [i[-1] for i in sorted(random_dict, key=lambda x:x[-1])][::-1])}
final_dict = {a:new_dict.get(a, b) for a, b in s.items()}
Output (randomly generated):
{'a': 'y', 'c': 'h', 'b': 'd'}

Accessing value which is nested inside 2 keys

Suppose I have the following dict:
L = {'A': {'root[1]': 'firstvalue', 'root[2]': 'secondvalue'}, 'B': {'root[3]': 'thirdvalue', 'root[4]': 'Fourthvalue'}}
How can I access the values of the keys root[1], root[2], root[3], root[4] (indexes of root[] is dynamic) in Python 2.7.
Try :
>>> L = {'A': {'root[1]': 'firstvalue', 'root[2]': 'secondvalue'}, 'B': {'root[3]': 'thirdvalue', 'root[4]': 'Fourthvalue'}}
>>> L['A']['root[1]']
'firstvalue'
>>> L['A']['root[2]']
'secondvalue'
>>> L['B']['root[3]']
'thirdvalue'
>>> L['B']['root[4]']
'Fourthvalue'
>>>
Something like this:
for (key, value) in L.items():
for (another_key, real_value) in value.items():
print(another_key, real_value)
To access the values from a dict nested inside the dict, i used the following step:
L = {'A': {'root[1]': 'firstvalue', 'root[2]': 'secondvalue'}, 'B': {'root[3]': 'thirdvalue', 'root[4]': 'Fourthvalue'}}
Solution:
F = {}
G = []
F = L.get("A", None)
F= {{'root[1]': 'firstvalue', 'root[2]': 'secondvalue'}}
for value in F.values():
G.append(value)
Output:
G = ['firstvalue', 'secondvalue']

Extract duplicate values from a dictionary

I am trying to find a way of deleting duplicate shaders in Maya using Python Dictionaries.
Here is what I'm doing:
I want to put all maya shaders into a dictionary as keys and put the corresponding texture file as the value. Then I want the script to run through the dictionary and find any keys that share the same value and stuff them into an array or another dictionary.
This is basically what I have right now:
shaders_dict = {'a': somePath, 'b': somePath,
'c': differentPath, 'd': differentPath}
duplicate_shaders_dict = {}`
how can I now run through that dictionary to compile another dictionary that looks something like this:
duplicate_shaders_dict = {'b':somePath, 'd':differentPath }
And the tricky part being since there are duplicates I want the script to skip the original key so it doesn't also get stuffed in to duplicate shaders dictionary.
I would probably do something like this. First, make the inverse dictionary:
>>> from collections import defaultdict
>>>
>>> shaders_dict = {'a':'somePath', 'b':'somePath', 'c':'differentPath', 'd':'differentPath'}
>>>
>>> inverse_dict = defaultdict(list)
>>> for k,v in shaders_dict.iteritems():
... inverse_dict[v].append(k)
...
>>> inverse_dict
defaultdict(<type 'list'>, {'differentPath': ['c', 'd'], 'somePath': ['a', 'b']})
This basically inverts the dictionary by looping over every key, value pair and appending the key to a list associated with the value.
Then split this:
>>> first_shaders_dict = {}
>>> duplicate_shaders_dict = {}
>>> for v, ks in inverse_dict.iteritems():
... first, rest = ks[0], ks[1:]
... first_shaders_dict[first] = v
... for r in rest:
... duplicate_shaders_dict[r] = v
...
>>> first_shaders_dict
{'a': 'somePath', 'c': 'differentPath'}
>>> duplicate_shaders_dict
{'b': 'somePath', 'd': 'differentPath'}
Hmm. This assumes that the texture files are hashable and so can serve as dictionary keys. If they're not, then I'd have to work around that. Also, since as #freespace notes there's no ordering here, if you wanted a particular order we'd have to iterate over sorted keys or the like.
--
Update: I didn't like the above much. Shorter itertools-based version:
>>> import itertools
>>> shaders_dict = {'a':'somePath', 'b':'somePath', 'c':'differentPath', 'd':'differentPath'}
>>> keys = sorted(sorted(shaders_dict),key=shaders_dict.get)
>>> by_val = [(v, list(ks)) for v, ks in itertools.groupby(keys, shaders_dict.get)]
>>> first_dict = dict((ks[0],v) for v,ks in by_val)
>>> duplicate_dict = dict((k,v) for v,ks in by_val for k in ks[1:])
>>> first_dict
{'a': 'somePath', 'c': 'differentPath'}
>>> duplicate_dict
{'b': 'somePath', 'd': 'differentPath'}
One simple solution is to reverse the dictionary. Given:
>>> d = {'a': 'somePath', 'b': 'somePath',
... 'c': 'differentPath', 'd': 'differentPath'}
You can reverse it like this:
>>> r = dict((v,k) for k,v in d.iteritems())
Which gives you:
>>> r
{'differentPath': 'd', 'somePath': 'b'}
And if you reverse that, you have the original dictionary with duplicates removed:
>>> d = dict((v,k) for k,v in r.iteritems())
>>> d
{'b': 'somePath', 'd': 'differentPath'}

Categories

Resources