Python pop dictionary list values - python

I have a dictionary:
{'dict': [['IE', '5', '-5'], ['UK', '3', '-9']]}
I wish to pop the list values that are outside of the UK, therefore taking the first value within the lists and comparing to see if it is equal to 'UK'.
I currently have:
for k,v in insideUK.items():
for i in v:
if i[0] == "UK":
print(x)
else:
k.pop(v)
I know after the else is wrong but need help!
I wish for the dict to look like this once finished popping values that aren't equal to "UK".
{'dict': [['UK', '3', '-9']]}

You can use a list comprehension to filter out based on the first element
>>> data = {'dict': [['IE', '5', '-5'], ['UK', '3', '-9']]}
>>> {'dict': [i for i in data['dict'] if i[0] == 'UK']}
{'dict': [['UK', '3', '-9']]}

You can also do it using the filter function:
d = {'dict': list(filter(lambda i: 'UK' in i, d['dict']))}
print(d)
Output:
{'dict': [['UK', '3', '-9']]}

A nested dict and list expression can do this:
{k: [i for i in v if i[0] == 'UK'] for k,v in insideUK.items()}
If you really want to do it with a for-loop and change the list in-place, you could do something like this:
for k,v in insideUK.items():
for i in v:
if i[0] == "UK":
print(x)
else:
v.remove(i)
But it is discouraged strongly to change the list you are iterating over during the iteration

Related

Split array based on value

I have an array:
foo = ['1', '2', '', '1', '2', '3', '', '1', '', '2']
¿Is there any efficient way to split this array into sub-arrays using '' as separator?
I want to get:
foo = [['1', '2'], ['1', '2', '3'], ['1'], ['2']]
In one line:
[list(g) for k, g in itertools.groupby(foo, lambda x: x == '') if not k]
Edit:
From the oficial documentation:
groupby
generates a break or new group every time the value of the key
function changes (which is why it is usually necessary to have sorted
the data using the same key function).
The key I generate can be True, or False. It changes each time we find the empty string element. So when it's True, g will contain an iterable with all the element before finding an empty string. So I convert this iterable as a list, and of course I add the group only when the key change
Don't know how to explain it better, sorry :/ Hope it helped
Create a list containing a single list.
output = [[]]
Now, iterate over your input list. If the item is not '', append it to the last element of output. If it is, add an empty list to output.
for item in foo:
if item == '':
output.append([])
else:
output[-1].append(item)
At the end of this, you have your desired output
[['1', '2'], ['1', '2', '3'], ['1'], ['2']]

Reusing an expression in a comprehension

Is it possible to reuse a subexpression that might be large, or expensive to compute, or non-idempotent like a generator, in a comprehension?
Say there is a list of strings to be to converted to a dict:
items = ['ab: 1', 'cd: 2', 'ef:3'] ===> {'ab': '1', 'cd': '2', 'ef': '3'}
A loop computes the "expensive" split expression once:
d = {}
for item in items:
k, v = item.split(':', maxsplit=1)
d.update({k.strip(): v.strip()})
A comprehension repeats the computation for each output element:
d = {x.split(':', maxsplit=1)[0].strip(): x.split(':', maxsplit=1)[1].strip() for x in items}
But the desired solution is a comprehension that computes the expression once and then reuses it:
d = {k.strip(): v.strip() for x in items for k, v in x.split(':', maxsplit=1)} # Wrong - need an assignment
Can it be done?
If you don't need a dictionary comprehension, the dict object already takes in tuples:
dict(map(str.strip, x.split(':')) for x in items)
# {'ab': '1', 'cd': '2', 'ef': '3'}
And this would be the dict comprehension if you want:
{k: v for k, v in [map(str.strip, x.split(':')) for x in items]}
# {'ab': '1', 'cd': '2', 'ef': '3'}
a = ['ab: 1', 'cd: 2', 'ef:3']
Using generator expression with map and a dictionary comprehension.
In [46]: b = (map(str.strip,thing.split(':')) for thing in a)
In [47]: d = {k:v for (k,v) in b}
In [48]: d
Out[48]: {'ab': '1', 'cd': '2', 'ef': '3'}
Each item in a is split once and the items in the resultant list are stripped once. Execution of those functions is delayed till the dictionary comprehension is executed.

Del list and next list element in list if string exist

I have an example:
list = [['2 a', 'nnn', 'xxxx','last'], ['next, next'], ['3', '4', 'next']]
for i in range(len(list)):
if list[i][-1] == "last":
del(list[i+1])
del(list[i])
I'd like to delete this list where the last item is "last" and the next item on the list.
In this example there is a problem every time - I tried different configurations, replacing with numpy array - nothing helps.
Trackback:
IndexError: list index out of range
I want the final result of this list to be ['3', '4', 'next']
Give me some tips or help how I can solve it.
Try this:
l = [['2 a', 'nnn', 'xxxx','last'], ['next, next'], ['3', '4', 'next']]
delete_next = False
to_ret = []
for x in l:
if x[-1] == 'last':
delete_next = True
elif delete_next:
delete_next = False
else:
to_ret.append(x)
Using a variable to store if this needs to be deleted
Loop over the list, if the last element of that iteration == 'last' then skip, else, append to a new list.
Also, it is not recommended to edit lists while iterating over them as strange things can happen, as mentioned in the comments above, like the indexes changing.
l = [['2 a', 'nnn', 'xxxx','last'], ['next, next'], ['3', '4', 'next']]
newlist = []
for i in l:
if i[-1] == 'last':
continue
else:
newlist.append(i)

How to add index to a list inside a dictionary

I have a dictionary here:
dict = {'A':['1','1','1','1','1'], 'B':['2','2'], 'C':['3','3','3','3']}
What is the necessary process to get the following result?
dict = {'A':['1_01','1_02','1_03','1_04','1_05'], 'B':['2_01','2_02'], 'C':['3_01','3_02','3_03','3_04']}
I have been learning python for quite a while now but dictionary is kind of new to me.
As others mentioned, refrain from using built-in keywords as variable names, such as dict. I kept it for simplicity on your part.
This is probably the most pythonic way of doing it (one line of code):
dict = {key:[x+"_0"+str(cnt+1) for cnt,x in enumerate(value)] for key,value in dict.items()}
You could also iterate through each dictionary item, and then each list item and manually change the list names as shown below:
for key,value in dict.items():
for cnt,x in enumerate(value):
dict[key][cnt] = x+"_0"+str(cnt+1)
Also, as some others have mentioned, if you want numbers greater than 10 to save as 1_10 rather than 1_010 you can you an if/else statement inside of the list comprehension...
dict = {key:[x+"_0"+str(cnt+1) if cnt+1 < 10 else x+"_"+str(cnt+1) for cnt,x in enumerate(value)] for key,value in dict.items()}
First iterate on keys.
Then loop on keys you are getting on key like for 'A' value is ['1','1','1','1','1'] then we can change the element at ['1','1','1','1','1']
enumerate() helps you iterate on index,value then index starts with zero as per your expected output add 1 to index. As you want the trailing 0 before each count we did '%02d'% (index+1)
Like this:
dict = {'A':['1','1','1','1','1'], 'B':['2','2'], 'C':['3','3','3','3']}
for i in dict.keys(): #iterate on keys
for index,val in enumerate(dict[i]): #took value as we have key in i
element='%02d'% (index+1) #add trailing 0 we converted 1 to int 01
dict[i][index]=val+"_"+ str(element) #assign new value with converting integer to string
print(dict)
Output:
{'A': ['1_01', '1_02', '1_03', '1_04', '1_05'], 'C': ['3_01', '3_02', '3_03', '3_04'], 'B': ['2_01', '2_02']}
Use enumerate to iterate over list keeping track of index:
d = {'A':['1','1','1','1','1'], 'B':['2','2'], 'C':['3','3','3','3']}
newd = {}
for k, v in d.items():
newd[k] = [f'{x}_0{i}' for i, x in enumerate(v, 1)]
print(newd)
Also a dictionary-comprehension:
d = {k: [f'{x}_0{i}' for i, x in enumerate(v, 1)] for k, v in d.items()}
Note: Don't name your dictionary as dict because it shadows the built-in.
d= {'A':['1','1','1','1','1'], 'B':['2','2'], 'C':['3','3','3','3']}
{x:[j + '_'+ '{:02}'.format(i+1) for i,j in enumerate(y)] for x,y in d.items()}
adict = {'A':['1','1','1','1','1'], 'B':['2','2'], 'C':['3','3','3','3'], 'D': '23454'}
newdict = {}
for i,v in adict.items():
if isinstance(v, list):
count = 0
for e in v:
count += 1
e += '_0' + str(count)
newdict[i] = newdict.get(i, [e]) + [e]
else:
newdict[i] = newdict.get(i, v)
print (newdict)
#{'A': ['1_01', '1_01', '1_02', '1_03', '1_04', '1_05'], 'B': ['2_01', '2_01', '2_02'], 'C': ['3_01', '3_01', '3_02', '3_03', '3_04'], 'D': '23454'}
This solution will check for whether your value in the dictionary is a list before assigning an index to it
You can use a dictcomp:
from itertools import starmap
d = {
'A': ['1', '1', '1', '1', '1'],
'B': ['2', '2'],
'C': ['3', '3', '3', '3']
}
f = lambda x, y: '%s_%02d' % (y, x)
print({k: list(starmap(f, enumerate(v, 1))) for k, v in d.items()})
# {'A': ['1_01', '1_02', '1_03', '1_04', '1_05'], 'B': ['2_01', '2_02'], 'C': ['3_01', '3_02', '3_03', '3_04']}

How to assign the values for dict(keys and values) into a new list? and also how to print the keys and values in the string dictionary?

I would like to print the keys and values of a string of dictionaries. For example,
a = [{'1': '0'}, {'9': '2'}, {'4': '3'}, {'3': '5'}, {'0': '7'}, [], [], [], []]
I tried this :
for x in a:
for y in x.values():
print(y)
not working
for x in a:
for y in x.itervalues():
print(y)
not working
for x in a:
for y in x.items():
print(y)
not working
Anyway to print it like this? :
1 0
9 2
4 3
3 5
0 7
or
keys = 1,9,4,3,0
values = 0,2,3,5,7
One possible solution is to filter out non-dictionaries using list comprehension, then convert the dictionaries into key-value tuples, and separate the keys and values with zip:
k,v = zip(*[list(x.items())[0] for x in a if isinstance(x, dict)])
print(k,v)
#('1', '9', '4', '3', '0') ('0', '2', '3', '5', '7')
And if you want the side by side key/value pair output, then you can do something like this (code would need to be altered if any of your dictionaries were going to contain more than one key/value pair):
for x in a:
if isinstance(x, dict):
# "if isinstance" is here just to ignore the lists in your list,
# you may want to do something else with those
print(x.keys(), x.values())
# (['1'], ['0'])
# (['9'], ['2'])
# (['4'], ['3'])
# (['3'], ['5'])
# (['0'], ['7'])
If you need to handle more than one key/value pair in the dictionary items and print just the values (minus the formatting), then something like this:
for x in a:
if isinstance(x, dict):
tups = x.items()
for tup in tups:
print('{} {}'.format(tup[0], tup[1]))
# 1 0
# 9 2
# 4 3
# 3 5
# 0 7

Categories