How to check if a key of multiple dictionary is the same and if it is copy the value and paste it to a new value but flipped.
dicts = [
{'A':1, 'B':2, 'C':10, 'D':100, 'E':None},
{'A':2, 'B':3, 'C':10, 'D':200, 'E':None},
{'A':3, 'B':4, 'C':20, 'D':300, 'E':None},
{'A':4, 'B':5, 'C':20, 'D':400, 'E':None},
{'A':5, 'B':6, 'C':30, 'D':500, 'E':None},
{'A':6, 'B':7, 'C':30, 'D':600, 'E':None}]
for x in dicts:
for y in dicts:
if y['C'] == x['C']:
# do something and flip the A value as below and copy it to E
print(dicts)
[{'A':1, 'B':2, 'C':10, 'D':100, 'E':2},
{'A':2, 'B':3, 'C':10, 'D':200, 'E':1},
{'A':3, 'B':4, 'C':20, 'D':300, 'E':4},
{'A':4, 'B':5, 'C':20, 'D':400, 'E':3},
{'A':5, 'B':6, 'C':30, 'D':500, 'E':7},
{'A':6, 'B':7, 'C':30, 'D':600, 'E':6}]
If there's just one match, just copy the value from A to E.
CodePudding user response:
You can solve this in linear time (i.e. not using a double loop) by keeping references to the found matches.
I am assuming here that there is a maximum of 2 matches per C:
dicts = [
{'A':1, 'B':2, 'C':10, 'D':100, 'E':None},
{'A':2, 'B':3, 'C':10, 'D':200, 'E':None},
{'A':3, 'B':4, 'C':20, 'D':300, 'E':None},
{'A':4, 'B':5, 'C':20, 'D':400, 'E':None},
{'A':5, 'B':6, 'C':30, 'D':500, 'E':None},
{'A':6, 'B':7, 'C':30, 'D':600, 'E':None}]
refs = {}
for i, d in enumerate(dicts):
if d['C'] in refs: # we already found the first match
j = refs[d['C']]
# swap the values
dicts[j]['E'], dicts[i]['E'] = dicts[i]['A'], dicts[j]['A']
else: # this is the first match
refs[d['C']] = i # keep a reference of the index
# copy A to E in case of a single match
d['E'] = d['A']
dicts
output:
[{'A': 1, 'B': 2, 'C': 10, 'D': 100, 'E': 2},
{'A': 2, 'B': 3, 'C': 10, 'D': 200, 'E': 1},
{'A': 3, 'B': 4, 'C': 20, 'D': 300, 'E': 4},
{'A': 4, 'B': 5, 'C': 20, 'D': 400, 'E': 3},
{'A': 5, 'B': 6, 'C': 30, 'D': 500, 'E': 6},
{'A': 6, 'B': 7, 'C': 30, 'D': 600, 'E': 5}]
CodePudding user response:
if there are always 2 possile duplicate of 'C' you can just make sure that x
and y
is different and then assign 'E':
dicts = [
{'A':1, 'B':2, 'C':10, 'D':100, 'E':None},
{'A':2, 'B':3, 'C':10, 'D':200, 'E':None},
{'A':3, 'B':4, 'C':20, 'D':300, 'E':None},
{'A':4, 'B':5, 'C':20, 'D':400, 'E':None},
{'A':5, 'B':6, 'C':30, 'D':500, 'E':None},
{'A':6, 'B':7, 'C':30, 'D':600, 'E':None}]
for x in dicts:
for y in dicts:
if y['C'] == x['C'] and y is not x:
x['E'] = y['A']
y['E'] = x['A']
print(dicts)
Output:
[{'A': 1, 'B': 2, 'C': 10, 'D': 100, 'E': 2},
{'A': 2, 'B': 3, 'C': 10, 'D': 200, 'E': 1},
{'A': 3, 'B': 4, 'C': 20, 'D': 300, 'E': 4},
{'A': 4, 'B': 5, 'C': 20, 'D': 400, 'E': 3},
{'A': 5, 'B': 6, 'C': 30, 'D': 500, 'E': 6},
{'A': 6, 'B': 7, 'C': 30, 'D': 600, 'E': 5}]
CodePudding user response:
Use itertools.combinations
to loop over your dicts:
import itertools
dicts = [
{'A':1, 'B':2, 'C':10, 'D':100, 'E':None},
{'A':2, 'B':3, 'C':10, 'D':200, 'E':None},
{'A':3, 'B':4, 'C':20, 'D':300, 'E':None},
{'A':4, 'B':5, 'C':20, 'D':400, 'E':None},
{'A':5, 'B':6, 'C':30, 'D':500, 'E':None},
{'A':6, 'B':7, 'C':30, 'D':600, 'E':None}]
for x, y in itertools.combinations(dicts, 2):
if x['E'] is None: # skip if already set
if x['C'] == y['C']:
x['E'] = y['A']
y['E'] = x['A']
This works because there is only ever one matching pair in the example dicts
. In case there is not, you should specify how to handle that case.
CodePudding user response:
Beware of the BigO : your 2 nested for loops equal to O(n^2).
You can reduce it with an hashtable.
dicts = [
{"A": 1, "B": 2, "C": 10, "D": 100, "E": None},
{"A": 2, "B": 3, "C": 10, "D": 200, "E": None},
{"A": 3, "B": 4, "C": 20, "D": 300, "E": None},
{"A": 4, "B": 5, "C": 20, "D": 400, "E": None},
{"A": 5, "B": 6, "C": 30, "D": 500, "E": None},
{"A": 6, "B": 7, "C": 30, "D": 600, "E": None},
]
c = {}
for i in range(len(dicts)):
if not c.get(dicts[i]["C"]):
c.update({dicts[i]["C"]: {"upper_row": i}})
else:
c[dicts[i]["C"]].update({"lower_row": i})
print(dicts)
print(c)
for value, duplicates in c.items():
lower = duplicates.get("lower_row")
if duplicates.get("lower_row"):
upper = duplicates.get("upper_row")
dicts[upper]["E"] = dicts[lower]["A"]
dicts[lower]["E"] = dicts[upper]["A"]
print(dicts)
Output :
"""
Original state of dicts :
[
{'A': 1, 'B': 2, 'C': 10, 'D': 100, 'E': None},
{'A': 2, 'B': 3, 'C': 10, 'D': 200, 'E': None},
{'A': 3, 'B': 4, 'C': 20, 'D': 300, 'E': None},
{'A': 4, 'B': 5, 'C': 20, 'D': 400, 'E': None},
{'A': 5, 'B': 6, 'C': 30, 'D': 500, 'E': None},
{'A': 6, 'B': 7, 'C': 30, 'D': 600, 'E': None}]
c hashtable :
{10: {'upper_row': 0, 'lower_row': 1}, 20: {'upper_row': 2, 'lower_row': 3}, 30: {'upper_row': 4, 'lower_row': 5}}
Final state of dicts:
[
{'A': 1, 'B': 2, 'C': 10, 'D': 100, 'E': 2},
{'A': 2, 'B': 3, 'C': 10, 'D': 200, 'E': 1},
{'A': 3, 'B': 4, 'C': 20, 'D': 300, 'E': 4},
{'A': 4, 'B': 5, 'C': 20, 'D': 400, 'E': 3},
{'A': 5, 'B': 6, 'C': 30, 'D': 500, 'E': 6},
{'A': 6, 'B': 7, 'C': 30, 'D': 600, 'E': 5}]
"""