1
{(0, 0): {(0, 1), (1, 0)},
 (0, 3): {(0, 2), (0, 4), (1, 3)},
 (0, 4): {(0, 3), (1, 4)},
 (1, 1): {(0, 1), (1, 0), (1, 2), (2, 1)},
 (1, 2): {(0, 2), (1, 1), (1, 3), (2, 2)},
 (2, 0): {(1, 0), (2, 1), (3, 0)},
 (2, 2): {(1, 2), (2, 1), (2, 3), (3, 2)},
 (2, 3): {(1, 3), (2, 2), (2, 4), (3, 3)},
 (2, 4): {(1, 4), (2, 3), (3, 4)},
 (3, 0): {(2, 0), (3, 1)},
 (3, 1): {(2, 1), (3, 0), (3, 2)},
 (3, 3): {(2, 3), (3, 2), (3, 4)}}

Above is a dictionary that I have obtained from a 2D List: keys -- tuples (co-ordinates) values -- set of tuples (co-ordinates)

The co-ordinates are cells in the 2D list.

My goal is to compare the value of given key with next key. example: compare {(0, 2), (0, 4), (1, 3)} with (0, 4). If the key is present in the value of the previous key then I would like to update the first value with values of the key that was found. For the given example: the result should be something like: {(0, 2), (0, 4), (1, 3), (0, 3), (1, 4)}.

I would like to know if this is even possible? Is there a way to compare values of a dictionary with keys of the same dictionary?

I was also thinking of using DFS but I do not have all the vertices for that. Is DFS the right approach?

petezurich
  • 9,280
  • 9
  • 43
  • 57
TheTank
  • 495
  • 2
  • 9
  • 21
  • Are your dictionary keys always sorted? – Mark Jun 17 '19 at 05:41
  • Note that if you use `.values()` and `.keys()` of given dictionary without dictionary-altering operation between, their order will correspond to each other. https://stackoverflow.com/questions/835092/python-dictionary-are-keys-and-values-always-the-same-order – Daweo Jun 17 '19 at 05:52
  • Is it fine if I restructure your data structure to try to come up with something? – Devesh Kumar Singh Jun 17 '19 at 05:52
  • @Daweo this seems to depend on keys being in a certain order : `compare the value of given key with next key` – Mark Jun 17 '19 at 06:05

1 Answers1

1

If you only want to do this to a given keys value then you could make a function to do this:

def get_value(data, key):
    keys = tuple(data)
    value = data[key]
    next_value = keys[keys.index(key)+1]
    next_value = data[next_value]

    return value | next_value if key in value else value | next_value

You can use it like this:

get_value(data, (0, 3))
#{(1, 3), (1, 4), (0, 4), (0, 3), (0, 2)}

If you want to do this to the whole dict then you could make a lookahead iterator, and compare them that way:

from itertools import zip_longest

data = {(0, 0): {(0, 1), (1, 0)},
 (0, 3): {(0, 2), (0, 4), (1, 3)},
 (0, 4): {(0, 3), (1, 4)},
 (1, 1): {(0, 1), (1, 0), (1, 2), (2, 1)},
 (1, 2): {(0, 2), (1, 1), (1, 3), (2, 2)},
 (2, 0): {(1, 0), (2, 1), (3, 0)},
 (2, 2): {(1, 2), (2, 1), (2, 3), (3, 2)},
 (2, 3): {(1, 3), (2, 2), (2, 4), (3, 3)},
 (2, 4): {(1, 4), (2, 3), (3, 4)},
 (3, 0): {(2, 0), (3, 1)},
 (3, 1): {(2, 1), (3, 0), (3, 2)},
 (3, 3): {(2, 3), (3, 2), (3, 4)}}

lookahead = iter(data.items()); next(lookahead)
for (k,v), (_k, _v) in zip_longest(data.items(), lookahead, fillvalue=(None,None)):
        if all((_k, _v)) and v >= {_k}:
                v |= _v

This results in:

{(0, 0): {(0, 1), (1, 0)},
 (0, 3): {(1, 3), (1, 4), (0, 4), (0, 3), (0, 2)},
 (0, 4): {(0, 3), (1, 4)},
 (1, 1): {(1, 3), (0, 2), (2, 1), (1, 0), (0, 1), (1, 2), (2, 2), (1, 1)},
 (1, 2): {(1, 3), (1, 1), (0, 2), (2, 2)},
 (2, 0): {(3, 0), (1, 0), (2, 1)},
 (2, 2): {(3, 2), (1, 3), (2, 1), (2, 3), (1, 2), (3, 3), (2, 2), (2, 4)},
 (2, 3): {(1, 3), (3, 3), (1, 4), (2, 3), (2, 2), (3, 4), (2, 4)},
 (2, 4): {(3, 4), (2, 3), (1, 4)},
 (3, 0): {(3, 2), (3, 0), (3, 1), (2, 1), (2, 0)},
 (3, 1): {(3, 0), (3, 2), (2, 1)},
 (3, 3): {(3, 4), (3, 2), (2, 3)}}

Note if you’re using python 3 you shouldn’t have an issue with ordering otherwise it’s safest to ensure the dict is in correct order and use a collections.OrderedDict especially in py2

Jab
  • 26,853
  • 21
  • 75
  • 114
  • Can you please explain the line `lookahead = iter(data.items()); next(lookahead)`? I'm trying to break it down but I'm not able to visualize the output. It says it's dictionary iterator, but not it's contents. Also is it possible to add to this logic to delete the key whose values are are placed into the values of the previous key? – TheTank Jun 22 '19 at 20:41
  • Take a look in the [docs](https://docs.python.org/3/library/stdtypes.html#dict.values) `dict.items()` returns a [`dictview`](https://docs.python.org/3/library/stdtypes.html#dictionary-view-objects) thus all that's happening is it's making a separate iterator over the dict's items and advancing it one time. If it makes it easier to read put the `next(lookahead)` onto it's own line and remove the semicolon. – Jab Jun 23 '19 at 08:38
  • You don't want to be removing keys from a dictionary as you iterate over it I' suggest using a dict comprehension or a completely separate loop: `keys = list(data) + [None]; removed = {k:v for i, (k, v) in enumerate(data.items()) if v >= {keys[i+1]}}` something like that? Where `removed` is the new dict? – Jab Jun 23 '19 at 08:57