haagn
haagn

Reputation: 163

Check if dict values exist as keys in another dict

I have two dictionaries:

concave = {6: [2, 3, 4, 5], 2: [6], 3: [6], 4: [6], 5: [6]}
convex = {1: [2, 3, 4, 5], 2: [1, 3, 5], 3: [1, 2, 4], 4: [1, 3, 5], 5: [1, 2, 4], 6: [7, 8, 9, 10], 7: [6, 8, 10, 11], 8: [6, 7, 9, 11], 9: [6, 8, 10, 11], 10: [6, 7, 9, 11], 11: [7, 8, 9, 10]}

And I have returned the keys which have max length values in the convex dict:

max_lens = [1, 6, 7, 8, 9, 10, 11]

For each number in max_lens, I want to check that it does not exist as a key in concave and its values in convex exist as keys in concave.

So in this example, '1' would satisfy this condition as it is not included in concave as a key, but its values in convex are (i.e. 2, 3 4 and 5).

I have tried to figure out how to go about this using for loops/if statements:

for i in enumerate(max_lens):
    if i not in concave:
        for k,v in convex.items():
            for j in v:

That is about as far as I got before getting totally confused. There must be an easier way to do this other than using multiple for loops and if statements?

I'm a bit of a python noob so sorry if this comes across as confusing!

Upvotes: 1

Views: 1620

Answers (5)

Tekay37
Tekay37

Reputation: 557

If you don't understand a problem easily, it's often a good way, to divide it into several smaller problems:

  1. write a function that checks if a value is not key of a dict:

def is_no_key_in(v, _dict): return key not in _dict

  1. Since that is too simple return a list of keys that are not in dict:

def no_key_values(_list, _dict): return [ v for v in _list if is_no_key_in(v, _dict) ]

  1. Now that you only have values that fit your first condition, you can concentrate on your second condition. Since you want that every value of a list is in a list of keys, you can start making a union-like function:

def union(a_lst, b_lst): return [ a for a in a_lst if a in b_lst]

  1. To make it more into something serving your needs, you could change it to a function that checks for any diffs:

def is_subset(a_lst, b_lst): return len([a for a in a_lst if a not in b_lst]) == 0

  1. Now you piece the functions together:

def satisfies_conditions(max_lens): for lens in no_key_values(max_lens, concave): if is_subset(convex[lens], concave.keys()) yield lens result = [ lens for lens in satisfies_conditions(max_lens) ]

result now contains all lenses that satisfy your conditions and if you want to change your conditions, you can easily do so. If your code works, you can go on and refactor it. For example you might not need is_no_key_in as it is a very simple function. Then go on and inline it into no_key_values:

def no_key_values(_list, _dict): return [ v for v in _list if v not in _dict ] If you write some tests before refactoring (or even writing the code) you can ensure, that your refactoring won't introduce bugs. Then simplify the code step by step. Maybe you will end up with a solution as simple as proposed in other answers here.

(I hope this will also help you with future problems like that :-))

Upvotes: 0

Rakesh
Rakesh

Reputation: 82765

Using a simple forloop.

concave = {6: [2, 3, 4, 5], 2: [6], 3: [6], 4: [6], 5: [6]}
convex = {1: [2, 3, 4, 5], 2: [1, 3, 5], 3: [1, 2, 4], 4: [1, 3, 5], 5: [1, 2, 4], 6: [7, 8, 9, 10], 7: [6, 8, 10, 11], 8: [6, 7, 9, 11], 9: [6, 8, 10, 11], 10: [6, 7, 9, 11], 11: [7, 8, 9, 10]}
max_lens = [1, 6, 7, 8, 9, 10, 11]

for i in max_lens:
    if (i not in concave):   #Check if not in key.
        if convex[i] in concave.values():   #Check Value.
                print i

Output:

1

Upvotes: 0

RoadRunner
RoadRunner

Reputation: 26315

Spelling this problem out into steps always helps:

  • Loop over each of the lengths l in max_lens
  • Check if l doesn't exist in concave but exists in convex. A conjunction of these two conditions is needed here. If either fails, don't continue.
  • If the above two conditions are accepted, check if all the values from convex[l] exist in concave.
  • If the code reaches here with no issues, all the conditions are met.

Demo:

concave = {6: [2, 3, 4, 5], 2: [6], 3: [6], 4: [6], 5: [6]}
convex = {1: [2, 3, 4, 5], 2: [1, 3, 5], 3: [1, 2, 4], 4: [1, 3, 5], 5: [1, 2, 4], 6: [7, 8, 9, 10], 7: [6, 8, 10, 11], 8: [6, 7, 9, 11], 9: [6, 8, 10, 11], 10: [6, 7, 9, 11], 11: [7, 8, 9, 10]}

max_lens = [1, 6, 7, 8, 9, 10, 11]

for l in max_lens:
    if l not in concave and l in convex and all(v in concave for v in convex[l]):
        print(l)

Output:

1

Upvotes: 1

FHTMitchell
FHTMitchell

Reputation: 12157

I think I understood (for the record I prefer the explicit concave.keys())

result_dict = {}
for convex_key in max_lens:
    result_dict[convex_key] = convex_key not in concave.keys() \
                              and all(convex_val in concave.keys() 
                                      for convex_val in convex[convex_key])

Edit (see comments)

for convex_key in max_lens:
    if convex_key not in concave.keys() and \
           all(convex_val in concave.keys() for convex_val in convex[convex_key]):
        top_face = convex_key
        break

Upvotes: 2

zipa
zipa

Reputation: 27869

You can do it with comprehension:

[i for i in max_lens if i not in concave and convex[i] in concave.values()]

Upvotes: 0

Related Questions