1

I have the following dict:

{('I', 'like'):14, ('he','likes'):2, ('I', 'hate'):12}

For a given word string I want to get the second element of all tuples in dictionary (which is a key of a dictionary) that has this word as the first element. I tried:

word='I'    
second_word = (k[0][1] for k, v  in d if word == k[0][0])
print(second_word)

and expected to get "like" as an answer but got:

<generator object generate_ngram_sentences.<locals>.<genexpr> at 0x7fed65bd0678>
<generator object generate_ngram_sentences.<locals>.<genexpr> at 0x7fed65bd0678>
<generator object generate_ngram_sentences.<locals>.<genexpr> at 0x7fed65bd06d0>
  1. How to get not only first occurrence but all of such occurrences in dictionary?

EDIT: 2. Can you share how could it be modified in case the size of the tuple to be dynamic. So that the key of the dict would store eg. 2elem tuple or 15elem etc. tuple depending on dict?

mCs
  • 2,591
  • 6
  • 39
  • 66

2 Answers2

3

You have the correct idea, but it needed to be fine tuned:

d = {('I', 'like'):14, ('he','likes'):2, ('I', 'hate'):12}

word='I'    
second_word = [k[1] for k in d if k[0] == 'I']
print(second_word)

The output is a list of all second words for all the lkeys whose first item is 'I'

['like', 'hate']

from there:

second_word[0] --> 'like'
Reblochon Masque
  • 35,405
  • 10
  • 55
  • 80
  • What would be the difference if I would put entire expression (in 3rd line) in right side of assignment instead of `[...]` into `(...)` in this case ? Second question: Can you share how could it be modified in case the size of the tuple to be dynamic. So that the key of the dict would store eg. 2elem tuple or 15elem etc. tuple depending on dict? – mCs Dec 02 '17 at 13:09
  • Sorry, I don't understand your question; can you please clarify? – Reblochon Masque Dec 02 '17 at 13:15
  • @mCs `(...)` is a generator expression, `[...]` is a list comprehension. See e.g. https://stackoverflow.com/questions/47789/generator-expressions-vs-list-comprehension – mkrieger1 Dec 02 '17 at 13:24
  • q1: kind of of topic question. the `[...]` builds a list in your answer. But if I would replace the brackets with the `(...)` I get: `. at 0x7fd8a7ccb678>...` So changing the braces from `[]` to `()` change it from list to something else. Why do I get this generator output? q2: How can one modify your answer for a dict with a key which would be a tuple of arbitrary size. eg. d1: 2elem key tuple ('I','am'), d2: 15elem key tuple('I','am',...<12 elements>,'.') – mCs Dec 02 '17 at 13:25
2

I steal the first sentence from Reblochon Masque's answer:

You have the correct idea, but it needed to be fine tuned:

second_word = (k[0][1] for k, v  in d if word == k[0][0])

Iterating directly over d generates the keys only (which are what you are interested in, so this was the right idea).

Now, for k, v in d actually works, not because you get the key and the value, but because the key is a tuple and you unpack the two items in the tuple to the names k and v.

So k already is the first word and v is the second word, and you don't need to use any indexing like [0][0] or [0][1].

Using different names makes it clearer:

word = 'I'
second_words = (second for first, second in d if first == word)

Note that now second_words is a generator expression and not a list. If you simply go on iterating over second_words this is fine, but if you actually want the list, change the generator expression to a list comprehension by replacing the () by [].

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • Thank you for the answer. Can you share how could it be modified in case the size of the tuple to be dynamic. So that the key of the dict would store eg. 2elem tuple or 15elem etc. tuple depending on dict? – mCs Dec 02 '17 at 13:13
  • If you're using Python 3 you can use [*extended tuple unpacking*](https://www.python.org/dev/peps/pep-3132/): Replace `for first, second in d` by `for first, second, *rest in d`. Then `rest` will be a list containing all remaining entries in the tuple (empty if the tuple has length 2). – mkrieger1 Dec 02 '17 at 13:20
  • Great, that is what I was looking for! :) – mCs Dec 02 '17 at 13:26