0

I've been trying to remove a specific item from multiple values in a dictionary in python and am not completely sure how to do this. For example, in the dictionary:

d  = {('hello', 'hi', 'how are you'): 2, ('hi', 'hello', 'how are you'): 1}

How would I remove 'hi' so that all that remains is:

d  = {('hello', 'how are you'): 2, ('hello', 'how are you'): 1}
7
  • Do you want to do this operation in place? Or is constructing a new dictionary OK? Commented Nov 26, 2012 at 19:11
  • What is your criteria? the first ocurrence? Commented Nov 26, 2012 at 19:11
  • Isn't better do something like 'd = {2:("hello", "hi", "how are you"), 1:("hi", "hello", "how are you")}' ? Commented Nov 26, 2012 at 19:13
  • 6
    Your second dictionary has duplicate keys. The result of evaluating {('hello', 'how are you'): 2, ('hello', 'how are you'): 1} is {('hello', 'how are you'): 1} Commented Nov 26, 2012 at 19:14
  • 4
    Your need to modify keys suggests that you are using the wrong data structure. Commented Nov 26, 2012 at 19:23

4 Answers 4

3

You apparently want to change the key. So you simply need to store the corresponding value with the new key and remove the old one. However, in your case creating a new dict is easier since you want to modify every single item.

d2 = {}
for key, value in d.iteritems():
    key = list(key)
    if 'hi' in key:
        key.remove('hi')
    d2[tuple(key)] = value

d2 now contains {('hello', 'how are you'): 1}

As you can see it contains only one value unlike in your example because dicts cannot contain the same key twice.

Sign up to request clarification or add additional context in comments.

1 Comment

Of course, the value in d2 might as well be 2, as dictionaries are unordered (specifically, iteration order is unspecified).
2

You won't get the expected output here, as both keys are now same. So, only one of them can be found in the resulting dict.

In [142]: d  = {('hello', 'hi', 'how are you'): 2, ('hi', 'hello', 'how are you'): 1}

In [143]: {tuple(y for y in x if y!='hi'):d[x] for x in d}
Out[143]: {('hello', 'how are you'): 1}

Comments

1

This should do it

answer = {}
for k,v in d.iteritems():
    key = tuple(i for i in k if i!='hi')
    answer[key] = v
d = answer

5 Comments

That just works for one of the keys, not for both example keys, and not for other similar keys. It also raises an exception because the dictionary is modified during iteration. -1
@delnan: Looks like I misread the question. Thanks for the bugreport; fixed now
The exception still occurs.
you can iterate over d.copy() to handle the exception.
Or (probably more idiomatic) list(d)/d.keys() (the latter doesn't fix the problem on 3.x).
1

Not sure if this works for you, but this creates a new dictionary and will sum the values of any keys that end up colliding after removing 'hi' (assuming that is what you want to do - if not, disregard this answer :) ):

>>> from collections import defaultdict
>>> new_d = defaultdict(int)
>>> for k, v in d.iteritems():
...   new_d[tuple(i for i in k if i != 'hi')] += v
...
>>> new_d
defaultdict(<type 'int'>, {('hello', 'how are you'): 3})

This does not correspond with your output, but as explained by everyone else, dictionaries can only have one key of a particular value, so this combines into one.

2 Comments

Why use a defaultdict and increment to re-create values (thus also typing yourself to a very limited set of types for the values)? Why not just re-insert the values into a normal dictionary?
@delnan I guess the main goal was trying to combine values of colliding keys, but agreed that this approach is limited in the case of not wanting to do that (in which case I'm not sure what the OP wants :) ).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.