python - remove dictionary from list if exists - python

I am trying to remove a dictionary from a list if it already exists but it doesn't seem to be working. Can anyone see what I am doing wrong or advise me what I should be doing
new_dict = {'value': 'some value', 'key': 'someKey'}
if new_dict in my_list:
my_list.remove(new_dict)
new_list is a list of dictionaries where new_dict is definitely in

If new_dict is "definitely" in my_list, then my_list.remove(new_dict) should do the trick (i.e., no need for the if new_dict in my_list, that just slows it down).

my_list = [1,{'value':'some value', 'key' :'somekey'}, 2, {'z':'z', 'x': 'x'}]
new_dict = {'value':'some value', 'key' :'somekey'}
#new_dict = {'z':'z', 'x': 'x'}
differ = 0
matched = 0
for element in my_list:
if type(element) is types.DictType and matched != 0:
differ = 0
# check if dictionary keys match
if element.viewkeys() == new_dict.viewkeys():
# check if dictionary values match
for key in element.keys():
if element[key] != new_dict[key]:
differ = 1
matched = 1
if differ != 1:
my_list.remove(new_dict)
print my_list
It worked for both of the dictionaries for me.

In most cases it is clever to build a new list:
new_list = [ dd for dd in my_list if not dd is new_dict ]
This is typical for a functional programming style, as it avoids side effects. Imagine if you use your solution in a function or method. In most cases you need a modified list only for internal purposes, then modifying an input parameter is dangerous.

Your problem may come from the fact that removing from a list while iterating over the same list is not safe. What you want to do is something like:
copied_list = my_list[:]
if new_dict in copied_list:
my_list.remove(new_dict)
This way, you iterate over a copy of the list and remove from the original.
This may not be the cause of your problem though. It would be interesting to see:
how you build my_list
what you do with my_list after the loop, i.e. how do you realise your dictionary was not removed

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)}

Purging empty dictionaries from list of dictionary

I have a list of dictionaries like so:
[{'a':'21'},{},{'b':20'},{'c':'89'},{}]
What's the most efficient way to purge empty dictionaries from this list, end result being:
[{'a':'21'},{'b':'20'},{'c':'89'}]
I'm trying:
new_list_of_dictionaries = []
for dictionary in list_of_dictionaries:
if dictionary:
new_list_of_dictionaries.append(dictionary)
return new_list_of_dictionaries
I don't suppose this can be done in O(1) or something?
Just use a list comprehension, and filter on the boolean truth. An empty dictionary is considered false:
return [d for d in list_of_dictionaries if d]
In Python 2, you could also use the filter() function, using None as the filter:
return filter(None, list_of_dictionaries)
In Python 3 that returns an iterator, not a list, so you'd have to call list() on that (so return list(filter(None, ...))), at which point the list comprehension is simply more readable. Of course, if you don't actually need to have random access to the result (so direct index access to result[whatever]), then an iterator might still be a good idea anyway.
Note that this has to take O(N) time, you have to test each and every dictionary. Even if lists had some kind of automaticly updated map that lets you get the indices of the dictionaries that are empty in O(1) time, removing items from a list requires moving later entries forward.
Comprehension or filter (Python2, Python3):
return filter(None, list_of_dictionaries)
# Python3, if you prefer a list over an iterator
return list(filter(None, list_of_dictionaries))
None as filter function will filter out all non-truthy elements, which in the case of empty collections makes it quite concise.
could use a list comprehension?
myList = [{'a':'21'},{},{'b':'20'},{'c':'89'},{}]
result = [x for x in myList if x]
I did it in this way
d = [{'a': '21'}, {}, {'b': 20}, {'c': '89'}, {}]
new_d = []
for item in d:
check = bool(item)
if not check:
del item
else:
new_d.append(item)
print(new_d)
[{'a': '21'}, {'b': 20}, {'c': '89'}]

Python dict key + list removal

Is there a way to make a list of keys of a dict excluding an specific one, in one single command?
Using two commands it can be done:
aDict = {'a': 'cat', 'b': 'dog', 'c': 'cow'}
list1 = aDict.keys()
list1.remove('b')
I'm looking for sth like list1 = aDict.keys().remove('b'). I know this doesn't work, but is there sth that works?
You can use a list comprehension to filter the results as you iterate across them. For example:
list1 = [key for key in aDict if key != 'b']
would do it.
What you're probably looking for is a list comprehension:
list1 = [key for key in aDict.keys() if key != 'b']
That said, the right answer might be to just use the example you provide. The Python style guide suggests writing your code to maximize the obviousness of what you are doing. Unless there's a good reason to do it in a one-liner, aim for the longer code that makes your intent clearer.

How to get dictionary in python list matching a given criteria

I have list of dictionaries-
[{"id":1,"name":"abc"},{"id":2,"name":"def"},{"id":3,"name":"xyz"}]
I want to get the dictionary where id = 1 and store it in a variable.Something like-
element = {"id":1,"name":"abc"}
I don't want to use for loop to iterate through the list and then fetch the element.
No matter what you do, you'll have to iterate over that list.
g = (e for e in elements if e.get('id') == 1)
element = next(g)
The nice thing about this implementation is it only iterates as much as needed to find the next matching element.
The problem you are addressing is called indexing. If you don't know anything about your matching criterias a priori then there is nothing you can do and you have to do the loop. The easiest implementation would be:
my_obj = next(obj for obj in my_list if my_criterium(obj))
where in your case
my_criterium = lambda obj: obj['id'] == 1
However if you know that you will always search by id then you can create an index:
my_index = {obj['id']: obj for obj in my_list}
Then the retrieveing is as simple as
my_obj = my_index[1]
which no longer requires a loop (and thus is fast).
This is under assumption that id is unique on each object (this assumption is not crutial, you can create a different index by storing a list of matched element for each id). The other drawback is that it will be hard to keep both the index and the list consistent between each other.
But no matter what path you chose there is no escape from a loop.
Dicts = [{"id":1,"name":"abc"},{"id":2,"name":"def"},{"id":3,"name":"xyz"}]
for d in Dicts:
if d.get('id') == 1:
element = d
print element
You can store the ids of your dictionary-list into another dictionary using just one for loop. This will be much faster when you have multiple queries.
In [1]: d = [{"id":1,"name":"abc"},{"id":2,"name":"def"},{"id":3,"name":"xyz"}]
In [2]: indices = {v["id"] : index for index, v in enumerate(d)}
In [3]: element = d[indices[1]]
In [4]: print(element)
{'id': 1, 'name': 'abc'}
In [5]: element = d[indices[3]]
In [6]: print(element)
{'id': 3, 'name': 'xyz'}
I think I have a solution.
Basically, you convert the list into a string and then you play with it to make a single dictionary.
Although, I think that looping over the list is way better.
l = [{"id":1,"name":"abc"},{"id":2,"name":"def"},{"id":3,"name":"xyz"}]
#convert to string
a = str(l)
#remove parenthesis and curly brackets
a = a.replace('{','').replace('}','').replace('[','').replace(']','').replace(' ','')
#remove 'id' and 'name'
a = a.replace("'id':",'').replace(",'name'",'')
#add curly brackets
a = '{'+a+'}'
#make a dict
exec('a='+a)
>>>a
{1: 'abc', 2: 'def', 3: 'xyz'}
As you can see, you end up with a single dictionary with the right key/value pairs without using a single for loop!

Replacing multiple occurrences in nested arrays

I've got this python dictionary "mydict", containing arrays, here's what it looks like :
mydict = dict(
one=['foo', 'bar', 'foobar', 'barfoo', 'example'],
two=['bar', 'example', 'foobar'],
three=['foo', 'example'])
i'd like to replace all the occurrences of "example" by "someotherword".
While I can already think of a few ways to do it, is there a most "pythonic" method to achieve this ?
for arr in mydict.values():
for i, s in enumerate(arr):
if s == 'example':
arr[i] = 'someotherword'
If you want to leave the original untouched, and just return a new dictionary with the modifications applied, you can use:
replacements = {'example' : 'someotherword'}
newdict = dict((k, [replacements.get(x,x) for x in v])
for (k,v) in mydict.iteritems())
This also has the advantage that its easy to extend with new words just by adding them to the replacements dict. If you want to mutate an existing dict in place, you can use the same approach:
for l in mydict.values():
l[:]=[replacements.get(x,x) for x in l]
However it's probably going to be slower than J.F Sebastian's solution, as it rebuilds the whole list rather than just modifying the changed elements in place.
Here's another take:
for key, val in mydict.items():
mydict[key] = ["someotherword" if x == "example" else x for x in val]
I've found that building lists is very fast, but of course profile if performance is important.

Categories

Resources