Python chaining - python

Let's say I have:
dic = {"z":"zv", "a":"av"}
## Why doesn't the following return a sorted list of keys?
keys = dic.keys().sort()
I know I could do the following and have the proper result:
dic = {"z":"zv", "a":"av"}
keys = dic.keys()
skeys = keys.sort() ### 'skeys' will be None
Why doesn't the first example work?

.sort doesn't return the list. You could do:
keys = sorted(dic.keys())

sort() modifies the contents of the existing list. It doesn't return a list. See the manual.

Related

Converting nested lists to dictionary with self generated keys

My list of lists looks like this:
my_list = [[sub_list_1],[sub_list_2],...,[sub_list_n]]
Desired output
my_dict[1] = [sub_list_1]
my_dict[2] = [sub_list_2]
my_dict[n] = [sub_list_n]
I want the keys for the dictionary to be generated on their own. How can this be achieved in a pythonic way?
I look at certain questions like
Converting list of lists in dictionary python
Python: List of lists to dictionary
Converting nested lists to dictionary
but they either provide a list of keys or focus on using some information from the lists as keys.
Alternatively, I tried making a list of keys this way:
my_keys = list(range(len(my_list)))
my_dict = dict(zip(my_keys,my_list)
and it works but, this does not:
my_dict = dict(zip(list(range(len(my_list))),my_list))
This gives me a syntax error.
So in summary:
Is there a way to generate a dictionary of lists without explicitly providing keys?, and
Why does the combined code throw a syntax error whereas the two step code works?
I would recommend to use a dict comprehension to achieve what you want like in here, moreover I tried your implementation and haven't faced any issues (more details are more than welcome):
my_list = [["sub_list_1"],["sub_list_2"],["sub_list_3"]]
my_dict = dict(zip(list(range(len(my_list))),my_list))
alternative_dict = {iter:item for iter,item in enumerate(my_list)}
print("yours : " + str(my_dict))
print("mine : " + str(alternative_dict))
output:
yours : {0: ['sub_list_1'], 1: ['sub_list_2'], 2: ['sub_list_3']}
mine : {0: ['sub_list_1'], 1: ['sub_list_2'], 2: ['sub_list_3']}
Your syntax error is caused by your variable name try. try is allready a name in python. see try/except
This should do it
my_dict = {my_list.index(i) + 1: i for i in my_list}
Notice that I have added +1 to start at the key 1 instead of 0 to match your expectations
I received no error message when running your code:
>>> my_list = [["hello1"], ["hello2"]]
>>> my_dict = dict(zip(list(range(len(my_list))), my_list))
>>> my_dict
{1: ['hello1'], 2: ['hello2']}
You can create a dict of lists from a list of lists using a dict comprehension:
my_dict = {i: sub_list for i, sub_list in enumerate(my_list)}

Python 3 is adding elements to a list regardless of key used in dict

I have a dict that I defined with:
keys = ['Valid', 'Reverse']
NOC = dict.fromkeys(keys, [])
I then iterate through a file and based on elements in the rows I add them to different lists in that dict based on a value in the row
This is code inside the list comprehension looping through the reader content:
if item[0] == '4':
if float(item[10]) < 0:
state = 'Reverse'
print(state)
NOC[state].append(item[6]+"FOOOO")
if float(item[10]) >= 0:
state = 'Valid'
print(state)
NOC[state].append(item[6])
print (NOC['Reverse'])
As you can see, I am adding the string "FOOOO" in the case of 'Reverse". I did this to see what was happening inside of the lists in the dict.
I have validated that the if-then statements are all working correctly.
However, the appends seem to be writing to the same place in memory. It's strange. Here is some output of the list comprehension looping through the file content:
Valid
['68382011714']
Valid
['68382011714', '69315013701']
Valid
['68382011714', '69315013701', '16729018201']
Valid
['68382011714', '69315013701', '16729018201', '54458098010']
Valid
['68382011714', '69315013701', '16729018201', '54458098010', '61570007301']
Valid
['68382011714', '69315013701', '16729018201', '54458098010', '61570007301', '61570007301']
Reverse
['68382011714', '69315013701', '16729018201', '54458098010', '61570007301', '61570007301', '61570007301FOOOO']
It makes no sense to me that print(NOC['Reverse']) is showing values that have anything other than those with the appended "FOOOO". Why is this happening?
You're creating only a single list with:
NOC = dict.fromkeys(keys, [])
which gets assigned to every key of NOC. Since the keys point to the same list, whatever key you use you'll get the same list back, hence you'll be modifying the same list. You can easily test that with:
assert NOC["Valid"] is not NOC["Reverse"], "It's the same list!"
Instead of doing that, make sure each key gets its own list as:
NOC = {k: [] for k in keys}
The problem is because the value for both the keys has same reference, when you create a dictionary from keys using NOC = dict.fromkeys(keys, [])
>>> keys = ['Valid', 'Reverse']
>>> NOC = dict.fromkeys(keys, [])
>>> NOC
{'Valid': [], 'Reverse': []}
>>> id(NOC['Valid'])
50173312
>>> id(NOC['Reverse'])
50173312
If you can see here both keys has reference to the same list. So when you are appending it is getting appended to the same list. So, I would prefer you to do something like this to create dictionary in order to avoid the above problem.
>>> keys = ['Valid', 'Reverse']
>>> NOC = dict.fromkeys(keys, [])
>>> for key in NOC.keys():
... NOC[key] = []
...
>>> NOC
{'Valid': [], 'Reverse': []}
>>> id(NOC['Valid'])
50173312
>>> id(NOC['Reverse'])
11515384
Now the append works perfect.
If the provided value is a mutable object (whose value can be modified) like list, dictionary, etc., when the mutable object is modified, each element of the sequence also gets updated.
This is because, each element is assigned a reference to the same object (points to the same object in the memory). you must be use dictionary comprehension
keys = ['Valid', 'Reverse']
NOC = { key: [] for key in keys }
Here the problem is that all values point to the same list. An efficient and Pythonic solution would be to use collections.defaultdict.
from collections import defaultdict
NOC = defaultdict(list)
Hope it satisfies your requirements.

how to iterate values of perticular keys in python dictionary?

I have something like this,
newlist = []
list =['a','b','c','d','e']
dict = {'a':['a','a1','a2','a3'],'b':['b','b1','b2','b3'],.....'e':['e','e1','e2','e3']
}
I have tried like this,
for listval in list:
newlist.append(dict[listval]].values())
But am not getting expected result,my expectation is,
newlist = [['a','a1','a2','a3'],['b','b1','b2','b3'],....,['e','e1','e2','e3']]
new_list = [the_dict[k] for k in the_list]
or if some keys might be missing:
new_list = [the_dict[k] for k in the_list if k in the_dict]
Try this - :
newlist = [dict.get(i) for i in list if dict.has_key(i)]
It will handle key exists and other errors.
Above will work for you.. :)
You can use map if you know for sure that all the keys will be in the list.
list1 =['a','b','c','d','e']
dict1 = {'a':['a','a1','a2','a3'],'b':['b','b1','b2','b3'],'c':['c','c1','c2','c3'],'d':['d','d1','d2','d3'],'e':['e','e1','e2','e3']}
newlist = map(dict1.get, list1)

Find out if no items in a list are keys in a dictionary

I have this list:
source = ['sourceid', 'SubSourcePontiflex', 'acq_source', 'OptInSource', 'source',
'SourceID', 'Sub-Source', 'SubSource', 'LeadSource_295', 'Source',
'SourceCode', 'source_code', 'SourceSubID']
I am iterating over XML in python to create a dictionary for each child node. The dictionary varies in length and keys with each iteration. Sometimes the dictionary will contain a key that is also an item in this list. Sometimes it wont. What I want to be able to do is, if a key in the dictionary is also an item in this list then append the value to a new list. If none of the keys in the dictionary are in list source, I'd like to append a default value. I'm really having a brain block on how to do this. Any help would be appreciated.
Just use the in keyword to check for membership of some key in a dictionary.
The following example will print [3, 1] since 3 and 1 are keys in the dictionary and also elements of the list.
someList = [8, 9, 7, 3, 1]
someDict = {1:2, 2:3, 3:4, 4:5, 5:6}
intersection = [i for i in someList if i in someDict]
print(intersection)
You can just check if this intersection list is empty at every iteration. If the list is empty then you know that no items in the list are keys in the dictionary.
in_source_and_dict = set(mydict.keys()).intersection(set(source))
in_dict_not_source = set(mydict.keys()) - set(source)
in_source_not_dict = set(source) - set(mydict.keys())
Iterate over the result of which one you want. In this case I guess you'll want to iterate over in_source_not_dict to provide default values.
In Python 3, you can perform set operations directly on the object returned by dict.keys():
in_source_and_dict = mydict.keys() & source
in_dict_not_source = mydict.keys() - source
in_source_not_dict = source - mydict.keys()
This will also work in Python 2.7 if you replace .keys() by .viewkeys().
my_dict = { some values }
values = []
for s in sources:
if my_dict.get(s):
values += [s]
if not values:
values += [default]
You can loop through the sources array and see if there is a value for that source in the dictionary. If there is, append it to values. After that loop, if values is empty, append the default vaule.
Note, if you have a key, value pair in your dictionary (val, None) then you will not append the None value to the end of the list. If that is an issue you will probably not want to use this solution.
You can do this with the any() function
dict = {...}
keys = [...]
if not any(key in dict for key in keys):
# no keys here
Equivalently, with all() (DeMorgan's laws):
if all(key not in dict for key in keys):
# no keys here

how can I do reverse sort in python language?

I have write python code,get the key from the log,and do descent sort by advert_sum,when i call sorted function,
sorted(dict, cmp=lambda x,y: cmp(adver_num), reverse=False)
it reports not adver_num. How can i fix it? dict[].adver_num? I try some ways,and it still failed.
import re
dict={}
class log:
def __init__(self,query_num, adver_num):
self.query_num = query_num
self.adver_num = adver_num
f = open('result.txt','w')
for line in open("test.log"):
count_result = 0
query_num = 0
match=re.search('.*qry=(.*?)qi.*rc=(.*?)dis',line).groups()
counts=match[1].split('|')
for count in counts:
count_result += int(count)
if match[0].strip():
if not dict.has_key(match[0]):
dict[match[0]] = log(1,count_result)
else:
query_num = dict[match[0]].query_num+1;
count_result = dict[match[0]].adver_num+count_result;
dict[match[0]] = log(query_num,count_result)
#f.write("%s\t%s\n"%(match[0],count_result))
sorted(dict,cmp=lambda x,y:cmp(adver_num),reverse=False)
for i in dict.keys():
f.write("%s\t%s\t%s\n"%(i,dict[i].query_num,dict[i].adver_num)
First of all, dict can't be sorted, you need to use a list. Second, sorted function does not modify its argument, but returns a new list. Try calling sorted on any dictionary, you'll get a sorted list of keys as a return value.
sorted returns a sorted copy of whatever you give it, which in this case is a list of the keys in dict. I think what you want is this:
s = sorted(dict.iteritems(), key=lambda x: x[1].adver_num, reverse=True)
for (i, _) in s:
…
I'm not sure why you passed reverse=False. That's the default (which means it's redundant, at the very least), and means that you don't want it sorted in reverse order.

Categories

Resources