1

My current code is ugly, so I'm looking for a more generic solution:

I have the following example python dictionary, with values as strings:

example_dict = {'key1':'AAAAAAAAAAA','key2':'BBBBAAABBBB', 'key3':'CAAAAAAACCC','key4':'DDDAADADAAA'}

Note that the strings are the same length, and only contain capital letters:

'AAAAAAAAAAA'
'BBBBAAABBBB'
'CAAAAAAACCC'
'DDDAADADAAA'

I would like to iterate over these strings, and find the indices whereby the string characters are the same. The following approach is what I'm not doing:

for i in range(11):
    if (example_dict['key1'][i]==example_dict['key2'][i]==example_dict['key3'][i]==example_dict['key4'][i]):
        print(i)

which works, as we see index 4 and 6 for all strings contain "A".

The problem is, I would like to do the same string comparison with other dictionaries, which have different key names (and more/less items).

For example, if I use the dictionary ex2 = {'one':'AAAAA', 'two':'ABBBA'}, I would need to change the above if statement to

if (ex2['one'][i]==ex2['two'][i]):

Is it possible to do comparisons of python dictionary values without explicitly naming the keys? Naturally, the above could is very ugly----the better question could be, is there a more generic way to do this task?

EB2127
  • 1,788
  • 3
  • 22
  • 43

2 Answers2

3

A solution exists with zip and list comprehension:

[i for i, x in enumerate(zip(*example_dict.values())) if len(set(x))==1]

Result:

[4, 6]

zip(*example_dict.values()) gives you the following results that line up each key by their index nicely:

[('A', 'B', 'C', 'D'),
 ('A', 'B', 'A', 'D'),
 ('A', 'B', 'A', 'D'),
 ('A', 'B', 'A', 'A'),
 ('A', 'A', 'A', 'A'),
 ('A', 'A', 'A', 'D'),
 ('A', 'A', 'A', 'A'),
 ('A', 'B', 'A', 'D'),
 ('A', 'B', 'C', 'A'),
 ('A', 'B', 'C', 'A'),
 ('A', 'B', 'C', 'A')]

All you need to do now is compare that each of these tuples have only one common value (len(set(x))==1) and return the index to list. enumerate gives you both the value (x, zipped tuple) and index (i).

r.ook
  • 13,466
  • 2
  • 22
  • 39
3

Would this work for you?

example_dict = {'key1': 'AAAAAAAAAAA', 'key2': 'BBBBAAABBBB',
                'key3': 'CAAAAAAACCC', 'key4': 'DDDAADADAAA'}

for i in range(11):
    index_values = [example_dict.get(k)[i] for k, v in example_dict.items()]
    if (len(set(index_values)) == 1):
        print(i)
Tommy
  • 346
  • 1
  • 5
  • I prefer r.ook's answer over mine. – Tommy May 17 '20 at 02:49
  • Nothing wrong with yours - if anything you could simplify the list comprehension to `[v[i] for v in example_dict.values()]`. Nobody says the shortest code is always the best, yours is more readable than mine :). – r.ook May 17 '20 at 02:53
  • 1
    True about the readability but I like the use of zip(), not the most readable function name but for those who knows zip() is like transpose then it's a good use case here. – Tommy May 17 '20 at 03:01
  • I think both answers are great---I'm choosing this, because I think the discussion is helpful. However, r.ook has a perfect answer as well. – EB2127 May 20 '20 at 01:27