python modifying dictionary values to another dict - python

I have a dictionary
a = {'aaa_key': ['aaa/aaa.csv', 'aaa/aaa.csv', 'aaa.csv'], 'bbb_key': ['bbb/bbb.csv', 'bbb/bbb.csv', 'bbb.csv']}
and I want to split / signs in inner lists values.
I use this code and print gives me right values like
aaa_key [['aaa', 'aaa.csv'], ['aaa', 'aaa.csv'], ['aaa.csv']]
and
bbb_key [['bbb', 'bbb.csv'], ['bbb', 'bbb.csv'], ['bbb.csv']]
but when i try to print aa dictionary, it's lists happen to be empty {'aaa_key': [], 'bbb_key': []}. What am i doing wrong?
code sample
b = []
aa = dict()
for i in a:
for ii in a[i]:
b.append(str(ii).split('/'))
print str(i) + ' ' + str(b)
aa[i] = b
del b[:]
print aa

When you assign b to a dictionary value actually both the values and the b refer to one object and when you delete it with del b[:] actually you delete both.So you need to remove that part.
But as a more pythonic way you can simply use a dictionary comprehension to create your expected dictionary :
>>> {key:[i.split('/') for i in value] for key,value in a.items()}
{'aaa_key': [['aaa', 'aaa.csv'], ['aaa', 'aaa.csv'], ['aaa.csv']], 'bbb_key': [['bbb', 'bbb.csv'], ['bbb', 'bbb.csv'], ['bbb.csv']]}
Note that you can also reassign to a.

When you are purging the content of the list b it also purges the content of the dictionary values that was assigned from the same variable. Both the variable b and the dictionary value refers to the same list
Instead of purging the content, just associate the variable b to the reference of a new list, every time you loop in a new key.
Implementation
def foo(a):
aa = dict()
for i in a:
b = []
for ii in a[i]:
b.append(str(ii).split('/'))
aa[i] = b
return aa
Sample Run
>>> foo(a)
{'aaa_key': [['aaa', 'aaa.csv'], ['aaa', 'aaa.csv'], ['aaa.csv']], 'bbb_key': [['bbb', 'bbb.csv'], ['bbb', 'bbb.csv'], ['bbb.csv']]}

Related

What is the correct way to write this function?

I was making a program where first parameter is a list and second parameter is a list of dictionaries. I want to return a list of lists like this:
As an example, if this were a function call:
make_lists(['Example'],
[{'Example': 'Made-up', 'Extra Keys' : 'Possible'}]
)
the expected return value would be:
[ ['Made-up'] ]
As an second example, if this were a function call:
make_lists(['Hint', 'Num'],
[{'Hint': 'Length 2 Not Required', 'Num' : 8675309},
{'Num': 1, 'Hint' : 'Use 1st param order'}]
)
the expected return value would be:
[ ['Length 2 Not Required', 8675309],
['Use 1st param order', 1]
]
I have written a code for this but my code does not return a list of lists, it just returns a single list. Please can someone explain?
def make_lists(s,lod):
a = []
lol =[]
i = 0
for x in lod:
for y in x:
for k in s:
if(y==k):
lol.append(x.get(y))
i = i+1
return lol
Expected Output:
[ ['Length 2 Not Required', 8675309],['Use 1st param order', 1] ]
Output:
['Length 2 Not Required', 8675309, 1, 'Use 1st param order']
The whole point of dictionaries, is that you can access them by key:
def make_lists(keys, dicts):
result = []
for d in dicts:
vals = [d[k] for k in keys if k in d]
if len(vals) > 0:
result.append(vals)
return result
Let's have a look what happens here:
We still have the result array, which accumulates the answers, but now it's called result instead of lol
Next we iterate through every dictionary:
for d in dicts:
For each dictionary d, we create a list, which is a lookup in that dictionary for the keys in keys, if the key k is in the dictionary d:
vals = [d[k] for k in keys if k in d]
The specs don't detail this, but I assume if none of the keys are in the dictionary, you don't want it added to the array. For that, we have a check if vals have any results, and only then we add it to the results:
if len(vals) > 0:
result.append(vals)
Try this code - I've managed to modify your existing code slighty, and added explanation in the comments. Essentially, you just need to use a sub-list and add that to the master list lol, and then in each loop iteration over elements in lod, append to the sub-list instead of the outermost list.
def make_lists(s,lod):
a = []
lol =[]
i = 0
for x in lod:
## Added
# Here we want to create a new list, and add it as a sub-list
# within 'lol'
lols = []
lol.append(lols)
## Done
for y in x:
for k in s:
if(y==k):
# Changed 'lol' to 'lols' here
lols.append(x.get(y))
i = i+1
return lol
print(make_lists(['Example'], [{'Example': 'Made-up', 'Extra Keys' : 'Possible'}]))
print(make_lists(['Hint', 'Num'], [{'Hint': 'Length 2 Not Required', 'Num' : 8675309}, {'Num': 1, 'Hint' : 'Use 1st param order'}]))
Prints:
[['Made-up']]
[['Length 2 Not Required', 8675309], [1, 'Use 1st param order']]
A simpler solution
For a cleaner (and potentially more efficient approach), I'd suggest using builtins like map and using a list comprehension to tackle this problem:
def make_lists(s, lod):
return [[*map(dict_obj.get, s)] for dict_obj in lod]
But note, that this approach includes elements as None in cases where the desired keys in s are not present in the dictionary objects within the list lod.
To work around that, you can pass the result of map to the filter builtin function so that None values (which represent missing keys in dictionaries) are then stripped out in the result:
def make_lists(s, lod):
return [[*filter(None, map(dict_obj.get, s))] for dict_obj in lod]
print(make_lists(['Example'], [{'Extra Keys' : 'Possible'}]))
print(make_lists(['Hint', 'Num'], [{'Num' : 8675309}, {'Num': 1, 'Hint' : 'Use 1st param order'}]))
Output:
[[]]
[[8675309], ['Use 1st param order', 1]]

Iterating through a dictionary of lists and returning the character at the same index

Working on printing a vertical column from a matrix passed as a string.
I've created a dictionary and assigned each row of the matrix as a value in the dict then bracketed to create a dictionary of lists.
Would like to iterate through each key in the dict and append the value of the given index (e.g. if value is 'a b c', return 'a' for 1, ' ' for 2...) but all I keep getting is:
[['a b c '], ['a b c '], ['a b c ']]
Or variations on this when I fiddle with it. It never seems to get past row 1, although each value is clearly a different row in the matrix.
Appreciate any help.
def column (str, index):
output = []
li = str.split("\n")
row_dict = {
1: [li[0]],
2: [li[1]],
3: [li[2]]
}
for key in row_dict:
output.append(row_dict[index])
return output
str = "a b c \n d e f \n g h i"
column(str, 1)
First, split on "\n " because you seem to have a whitespace after each newline.
Getting the nth item of each row is pretty straightforward if you use list comprehensions, e.g. [row[index] for row in s.split("\n ")].
Altogether:
>>> def column (s, index):
return [row[index] for row in s.split("\n ")]
>>> s = "a b c \n d e f \n g h i"
>>> column(s, 1)
[' ', ' ', ' ']
Or, if you want it to be 1-indexed (like in the example in the question) instead of 0-indexed:
>>> def column (s, index):
return [row[index-1] for row in s.split("\n ")]
>>> s = "a b c \n d e f \n g h i"
>>> column(s, 1)
['a', 'd', 'g']
As far as I can see, the only issue with your code is that you are appending the dictionary value (which is a row, and not the actual value, for example it is getting the row at key = 'index', rather than the value at location 'index' in each of the dictionaries) to output, when you want to assign a particular value from each row... this is what you should be doing:
for key in row_dict:
output.append(row_dict[key].split()[index])
print (row_dict[key].split()[index])
For index=1, this will print:
b
e
h
This does three things in one statement:
gets the string stored at key='key' from dictionary
splits your string into individual characters (so you can extract them more easily)
Gets the character/word at the index specified by your parameters.
You probably forgot to mention the key on which you were iterating. Your function should be something like:
def column(str, index):
output = []
li = str.split("\n")
row_dict = {
1: li[0].lstrip().split(' '),
2: li[1].strip().split(' '),
3: li[2].strip().split(' ')
}
for key in row_dict:
output.append(row_dict[key][index])
return output
Also, note that you were adding extra [] to the values of the row_dict. Finally, iterable objects in Python start from a 0th index, so you would call your function like column("a b c \n d e f \n g h i", 0).
Hope it helps.

Read python list correctly

I have defined a function that takes in a list like this
arr = ['C','D','E','I','M']
I have another function that produces a similar kind of list, the function is:
def tree_count(arr):
feat = ['2','2','2','2','0']
feat_2 = []
dictionary = dict(zip(arr, feat))
print('dic',dictionary)
feat_2.append([k for k,v in dictionary.items() if v=='2'])
newarr = str(feat_2)[1:-1]
print(newarr)
This outputs the correct result that I want, i.e:
['C','D','E','I']
But the problem is, when I use this list in another function, its values should be read as C,D,E,I . But instead when I print this, the bracket [ and ' are included as result:
for i in newarr:
print(i)
The printed result is : [ ' C ', and so on for each line. I want to get rid of [ '. How do I solve this?
For some reason you are using str() on the array, this is what causes the square brackets from array to appear in the print statement.
See if the following methods suit you:
print(arr) # ['C','D','E','I'] - the array itself
print(str(arr)) # "['C', 'D', 'E', 'I']" - the array as string literal
print(''.join(arr)) # 'CDEI' - array contents as string with no spaces
print(' '.join(arr)) # 'C D E I' - array contents as string with spaces
Make your function return the dictionary rather than just printing it:
def tree_count(arr):
feat = ['2','2','2','2','0']
dictionary = dict(zip(arr, feat))
dictionary = [k for k in dictionary if dictionary[k] == '2']
return dictionary
For instance,
$ results = tree_count(['C','D','E','I','M'])
$ print(results)
['I', 'C', 'D', 'E']
Pretty-printing is then fairly straightforward:
$ print("\n".join(results))
I
C
D
E
... or if you just want ,:
$ print(", ".join(results))
I, C, D, E

how can delete/remove values from list/set/dict in Python?

I created a list, a set and a dict and now I want to remove certain items from them
N = [10**i for i in range(0,3)] #range(3,7) for 1000 to 1M
for i in N:
con_list = []
con_set = set()
con_dict = {}
for x in range (i): #this is the list
con_list.append(x)
print(con_list)
for x in range(i): #this is the set
con_set.add(x)
print(con_set)
for x in range(i): #this is the dict
con_dict = dict(zip(range(x), range(x)))
print(con_dict)
items to remove
n = min(10000, int(0.1 * len(con_list)))
indeces_to_delete = sorted(random.sample(range(i),n), reverse=True)
now if I add this:
for a in indeces_to_delete:
del con_list[a]
print(con_list)
it doesn't work
Need to do the same for a set and a dict
Thanks!
You can use pop
On a dict:
d = {'a': 'test', 'b': 'test2'}
calling d.pop('b') will remove the key/value pair for key b
on list:
l = ['a', 'b', 'c']
calling l.pop(2) will remove the third element (as list index start at 0)
Beware on set:
s = {'a', 'b', 'c'}
calling s.pop() will remove a random element as discussed here: In python, is set.pop() deterministic?
you should use s.discard('a') to remove element 'a'
More infos here: https://docs.python.org/2/tutorial/datastructures.html

Type error when trying to access the dict value

i have a dict
d1={'a':['in-gaap','inr',0,1],'b':['in-gaap','inr',0,2],'c':['in-ca','share',0,4],'n1':['','','','aaa']}
d2={'d':['in-gaap','inr',0,'a+b'],'e':['in-gaap','inr',0,'y+t']}
for k in d2.iterkeys():
a=re.findall('\w+',d2[k][3])
x2=dict([(x,d1.get(x,0)[3])for x in a]) # here its showing Type:error int obj not subscriptable
d1[k]=[d2[k][0],d2[k][1],d2[k][2],eval(d2[k][3],x2)]
'a' is a list dynamically created it splits d[k][3] and stores it in "a"
d[k][3] contains in first iteration a=['a','b'] and in second iteration a=['y','t']
Actually i am comparing list "a" keys with dict "d1" keys if key is their it takes that value or it assigns default value,upto this its working fine.
But when i try to create dict by comparing list "a" with dict "d1" ,by using code
x2=dict([(x,d1.get(x,0)[3])for x in a])
it shows Type:error int object not subsricptable. i dono y but d2[k][3] has value but it showing error.
d1.get(x,0)[3]. This is your problem. If x isn't in d1, d1.get(x,0) returns 0. And 0[3] is a TypeError.
Replace the problem line with these lines, and it should work, assuming I read your intent correctly:
values = [d1[x][3] if x in d1 else 0 for x in a]
x2 = dict(zip(a, values))
This is slightly easier to read too.
import re
d1={'a':['in-gaap','inr',0,1],'b':['in-gaap','inr',0,2],'c':['in-ca','share',0,4],'n1':['','','','aaa']}
d2={'d':['in-gaap','inr',0,'a+b'],'e':['in-gaap','inr',0,'y+t']}
for k in d2.iterkeys():
a=re.findall('\w+',d2[k][3])
print a
for x in a:
print 'x is :',x # at first iteration **x=='y'** so **d1.get(x,0)** will return **0** so you can't get **d1.get(x,0)[3]**
print d1.get(x,0)
output
['y', 't']
x is : y
0
x is : t
0
['a', 'b']
x is : a
['in-gaap', 'inr', 0, 1]
x is : b
['in-gaap', 'inr', 0, 2]

Categories