Amrith Krishna
Amrith Krishna

Reputation: 2853

Python List comprehension when item index is required

I am attempting to write the corresponding list comprehension for the following code snippet.

# Initialize data.
queryRelDict = {'1': [1, 2, 3],
                '2': [4, 5, 6],
                '3': [11, 13, 14]}
related_docs_indices = [1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 14]

relOrNot = [0] * k
for item in queryRelDict.keys():
    for i in range(len(related_docs_indices)):
        if related_docs_indices[i] + 1 in queryRelDict[item]:
            relOrNot[i] = 1  

Basically I have a dictionary, where each key has a list as its value. Now my list relOrNot[i] needs to be 1, if ith element of related_docs_indices is in either of the lists in the dictionary.

The desired Output is:

[1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1]

I tried the following two variations, but is not able to get the desired output.

relOrNot2 = [1 for item in queryRelDict.keys() for i in range(len(related_docs_indices)) if related_docs_indices[i] + 1 in queryRelDict[item]]

but the output is

[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

I also tried

relOrNot2 = [1 if related_docs_indices[i] + 1 in queryRelDict[item] else 0 for item in queryRelDict.keys() for i in range(len(related_docs_indices))]

Corresponding Output:

[0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]

What modification is necessary to get the desired output?

Upvotes: 0

Views: 163

Answers (4)

hosyvietanh
hosyvietanh

Reputation: 286

Here if you want an one-liner :)

relOrNot = [1 if v in set().union(*queryRelDict.values()) else 0 for v in related_docs_indices]

Upvotes: 1

Benjamin
Benjamin

Reputation: 3477

Create a set with all keys and all values and in your loop just look if the required value is in the set.

s = set()
for (k,v) in queryRelDict.items():
    s.add(int(k))# because your keys are string
    s = s | set(v)
map(lambda x:1 if x in s else 0, related_docs_indices)

=>[1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1]

Upvotes: 1

Alexander
Alexander

Reputation: 109666

For each key, you are iterating through the related_doc_indices and checking if there is a matching value within the set of values for that key. For key '1', it would look like this:

key 1 values = [1, 2, 3]

related_docs_indices = [
    1, # 1 (match)
    2, # 1 (match)
    3, # 1 (match)
    4, # 0 (no match)
    5, # 0 (no match)
    6, # 0 (no match)
    7, # 0 (no match)
    8, # 0 (no match)
    12, # 0 (no match) 
    13, # 0 (no match)
    14] # 0 (no match)

The desired output for this key should thus be:

[1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]

One issue that you have is that keys are unordered in dictionaries, so that results of the longer list can vary depending on the random order of the keys. For example:

>>> queryRelDict.keys()
['1', '3', '2']

Let's say you first sort the keys, then I believe the desired output should look like this:

[1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,  # key '1'
 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,  # key '2'
 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]  # key '3'

keys = queryRelDict.keys()
keys.sort()
>>> [1 if i in queryRelDict.get(item) else 0 
     for item in keys for i in related_docs_indices]
#[1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 14] related_doc_indices
[1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,  # key '1' values: [1, 2, 3]
 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,  # key '2' values: [4, 5, 6]
 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]  # key '3' values: [11, 13, 14] (note 11 is not in related_doc_indices)

Upvotes: 1

Julien Spronck
Julien Spronck

Reputation: 15433

If your desired output is a list relOrNot, where relOrNot[i] is 1, if ith element of related_docs_indices is in either of the lists in the dictionary queryRelDict (then it must have the same length as related_docs_indices), then you can do the following:

# first create one flat list with all elements of the sublists in the dictionary
flatlist = [i for sublist in queryRelDict.itervalues() for i in sublist]
relOrNot = [1 if i in flatlist else 0 for i in related_docs_indices]
# [1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1]

Upvotes: 1

Related Questions