Merging Two Arrays of Dictionaries Based on a Shared Value

How to merge two list of dictionaries based on a value

You can keep track of the ids with another dict (or defaultdict to make things simpler). Then update the items in that dict as you iterate. In the end the dict's values will have your list.

from collections import defaultdict
d = defaultdict(dict)

a = [{'id': 1, 'name': 'a'}, {'id': 3, 'name': 'a'}]
b = [{'id': 1, 'city': 'b'}, {'id': 2, 'city': 'c'}, {'id': 3, 'city': 'd'}]

for item in a + b:
d[item['id']].update(item)
list(d.values())

# [{'id': 1, 'name': 'a', 'city': 'b'},
# {'id': 3, 'name': 'a', 'city': 'd'},
# {'id': 2, 'city': 'c'}]

Note this will overwrite duplicate values other than id — so if you have two with id: 1 and two different cities, you will only get the last city.

How to merge dicts, collecting values from matching keys?

assuming all keys are always present in all dicts:

ds = [d1, d2]
d = {}
for k in d1.iterkeys():
d[k] = tuple(d[k] for d in ds)

Note: In Python 3.x use below code:

ds = [d1, d2]
d = {}
for k in d1.keys():
d[k] = tuple(d[k] for d in ds)

and if the dic contain numpy arrays:

ds = [d1, d2]
d = {}
for k in d1.keys():
d[k] = np.concatenate(list(d[k] for d in ds))

Merging arrays of dictionaries based on dates

I found a way, assuming data is inside a structure(not a dic) which is a better practice.

I will put all arrays into a single large array, sort it by dates, loop on it and as long as date is equal previous date(or close enough to equality), I will sum the values up. When the next date is different, I will save the date and the sum.

       //create a combined array from all given arrays
var combined = [RootData]()
for list in dataSets {combined.append(contentsOf: list)}

//sort it by dates
let sortedArray = combined.sorted { $0.date < $1.date }

//new array - sum of all
var sumData = [RootData]()

var last:Date = sortedArray[0].date //set starting point
var sum:CGFloat = 0
for element in sortedArray
{
//same date - accumulate(same is less than 1 sec difference)
if(abs(element.date.seconds(from: last)) <= 1) {
sum+=element.value
}
//save
else {
sumData.append(RootData(value:sum,date:last))
sum=element.value
}
last=element.date
}
//last object
sumData.append(RootData(value:sum,date:last))

return averageData

Here RootData is a simple structure for the data with :

value:CGFloat
date:Date

Works as expected.
Because dates are not always completely equal , I check equality by assuming 1 second or less is the same date.

Merge two list of dictionaries based on a condition

There are two algorithmic tasks in what you need: find the records that have the same values for USA and GOOGL, and then joining then and do that in a way that if the same key exists in both records, their value is merged.

The naive approach for the first would be to have a for loop that would iterate the values of list1, and for each value, iterate all values for list2 - two separated loops won't cut it, you'd need two nested for loops:

for element in list1:
for other_element in list2:
if ...:
...

While this approach would work, and is fine for small lists (<1000 records, for example), it takes an amount of time and resources that are proportional to the square of your list sizes - that is, for lists that are close to ~1000 items we are talking 1 million iterations. If the lists are thenselves 1.000.000 items, the computation would take 1 * 10^12 comparisons, and that is not feasible in today's computers at all.

So, a nice solution is to re-create one of the lists in a way that the comparison key is used as a hash -that is done by copying the list to a dictionary where the keys are the values you want to compare, and then iterate on the second list just once. As dictionaries have a constant time to find items, that will make the number of comparisons be proportional to your list sizes.

The second part of your task is to compare to copy one record to a result list, and update the keys on the resulting copy so that any duplciate keys are merged. To avoid a problem when copying the first records, we are safer using Python's copy.deepcopy, which will ensure the sub-dictionaries are different objects than the ones in the original record, and will stay isolated.

from copy import deepcopy

def merge_lists(list1, list2):
# create dictionary from list1:
dict1 = {(record["GOOG"], record["USA"]): record for record in list1}

#compare elements in list2 to those on list1:

result = {}
for record in list2:
ckey = record["GOOG"], record["USA"]
new_record = deepcopy(record)
if ckey in dict1:
for key, value in dict1[ckey].items():
if key in ("GOOG", "USA"):
# Do not merge these keys
continue
# Dict's "setdefault" finds a key/value, and if it is missing
# creates a new one with the second parameter as value
new_record.setdefault(key, {}).update(value)

result[ckey] = new_record

# Add values from list1 that were not matched in list2:
for key, value in dict1.items():
if key not in result:
result[key] = deepcopy(value)

return list(result.values())

Merge two arrays of dictionaries in javascript

You can use Array#map method to generate the new array( assuming both arrays are in the same order ).

var lat = [{key:"2017-09-20T11:51:32.000Z", value:50.7825333},{key:"2017-09-20T11:51:33.000Z", value:50.7826}];var lon = [{key:"2017-09-20T11:51:32.000Z", value:-1.3075833},{key:"2017-09-20T11:51:33.000Z", value:-1.3076}];

var res = lat // iterate over the first array .map(function(o, i) { // generate the array element // where get values from element and // get value from second array using // the index return { time: o.key, lat: o.value, lon: lon[i].value } })
console.log(res);
// with ES6 arrow functionvar res1 = lat.map((o, i) => ({time: o.key, lat: o.value, lon: lon[i].value}))

console.log(res1);

Merge two array of objects based on a key

You can do it like this -

let arr1 = [    { id: "abdc4051", date: "2017-01-24" },    { id: "abdc4052", date: "2017-01-22" }];
let arr2 = [ { id: "abdc4051", name: "ab" }, { id: "abdc4052", name: "abc" }];
let arr3 = arr1.map((item, i) => Object.assign({}, item, arr2[i]));
console.log(arr3);

combine dictionaries in list of dictionaries based on matching key:value pair

You could do the following:

from collections import defaultdict
from functools import reduce
from itertools import chain

def merge(d1, d2, key='A'):
r = defaultdict(list)

for k, v in chain(d1.items(), d2.items()):
if k != key:
r[k].extend(v if isinstance(v, list) else [v])

return {**r, key: d1[key]}

d1 = {'A': 'str1', 'B': 41, 'C': 32}
d2 = {'A': 'str1', 'B': 12, 'C': 62}
d3 = {'A': 'str2', 'B': 47, 'C': 73}
d4 = {'A': 'str2', 'B': 101, 'C': 93}

common = defaultdict(list)
for d in [d1, d2, d3, d4]:
common[d['A']].append(d)

result = [reduce(merge, value) for value in common.values()]

print(result)

Output

[{'B': [41, 12], 'C': [32, 62], 'A': 'str1'}, {'B': [47, 101], 'C': [73, 93], 'A': 'str2'}]


Related Topics



Leave a reply



Submit