Consolidating Duplicate Array Items

combining duplicate values in JavaScript array

You can use reduce to group the array into an object. Use concat to merge arrays. Use Object.values to convert the object to array.

let data = [  {"key":11,"numbers":[555,556,557]},  {"key":22,"numbers":[444,772,995,667]},  {"key":11,"numbers":[223,447]},  {"key":45,"numbers":[999,558,367]},  {"key":45,"numbers":100}];
let result = Object.values(data.reduce((c, {key,numbers}) => { c[key] = c[key] || {key,numbers: []}; c[key].numbers = c[key].numbers.concat(Array.isArray(numbers) ? numbers : [numbers]); return c;}, {}));
console.log(result);

Consolidating duplicate array items

array =  [
{
'keyword' => 'A',
'total_value' => 50
},
{
'keyword' => 'B',
'total_value' => 25
},
{
'keyword' => 'C',
'total_value' => 40
},
{
'keyword' => 'A',
'total_value' => 10
},
{
'keyword' => 'C',
'total_value' => 15
}]

m = array.inject(Hash.new(0)) do |hs,i|
hs[i['keyword']] += i['total_value']
hs
end
p m

Output:

{"A"=>60, "B"=>25, "C"=>55}

By consolidate, I mean combine total_values. For example, after consolidation of the above array, there should only be one hash with 'keyword' => 'A' with a 'total_value => 60

Here is how it can be done:

m = array.each_with_object(Hash.new(0)) do |h,ob| 
if h['keyword'] == 'A'
h['total_value'] += ob['total_value']
ob.update(h)
end
end
p m
#=> {"keyword"=>"A", "total_value"=>60}

How to consolidate duplicate elements of this array in PHP?

Please use below code to make the solution what you want

<?php 

$array = array(
0 => array("ordernumber" => "1", "name" => "John", "product" => "laptop", "component" => "memory"),
1 => array("ordernumber" => "1", "name" => "John", "product" => "laptop", "component" => "cpu"),
2 => array("ordernumber" => "1", "name" => "John", "product" => "desktop", "component" => "cpu"),
3 => array("ordernumber" => "2", "name" => "Pete", "product" => "monitor", "component" => "")
);

$final_array = [];
foreach($array as $k=>$v){
$final_array[$v['ordernumber']]['order']['ordernumber'] = $v['ordernumber'];
$final_array[$v['ordernumber']]['order']['name'] = $v['name'];

$final_array[$v['ordernumber']]['products'][$v['product']]['name'] = $v['product'];
$final_array[$v['ordernumber']]['products'][$v['product']]['components'][] = $v['component'];
}

// You can skip this foreach if there will not metter of KEY of an array in your code!
$final_array = array_values($final_array);
foreach($final_array as $k=>$v){
$final_array[$k]['products'] = array_values($final_array[$k]['products']);
}

echo "<pre>";
print_r($final_array);

?>

its should work!!

How to combine duplicate element of an array of objects into one using javascript

You can group your object using array#reduce on the Company key in an object and extract all the values using Object.values().

var myArr=[{ "Company": "Samsung", "model": "Galaxy S2", "screen_size": "5.5" }, { "Company": "Samsung", "model": "Galaxy S3", "screen_size": "5.5" }, { "Company": "Samsung", "model": "Galaxy S4", "screen_size": "5.5" }, { "Company": "Xiaomi", "model":"Redmi 2", "screen_size": "4.7" }, { "Company": "Xiaomi", "model": "Redmi 4", "screen_size": "5" }, { "Company": "Xiaomi", "model": "Redmi Note 4", "screen_size": "5.5" } ],    result = Object.values(myArr.reduce((r,o) => {      r[o.Company] = r[o.Company] || {'Company': o.Company, 'Models' : []};      r[o.Company]['Models'].push({[o.model]:{'screen_size' : o.screen_size}});      return r;    }, {}));
console.log(result);

merge duplicate objects in an array and combine sub array of each object

I think, reduce() would do the job:

const accounts = [{"Id":103,"accountList":[{}]},{"Id":103,"accountList":[{"tokenId":"5aasdasdsdnjn3434nadd","featureId":2840}]},{"Id":112,"accountList":[{"tokenId":"5d30775bef4a722c38aefaaa","featureId":2877}]},{"Id":112,"accountList":[{"tokenId":"5d30775bef4a722c38aefccc","featureId":2856}]}];

const result = [...accounts
.reduce((r, o) => {
const record = r.get(o.Id)||{}
r.set(o.Id, {
Id: o.Id,
accountList: [
...(record.accountList||[]),
...o.accountList.filter(o =>
Object.keys(o).length != 0)
]
})
return r
}, new Map())
.values()]

console.log(result);
.as-console-wrapper {min-height: 100%}

Consolidate duplicate rows of an array

A pure NumPy solution could work like this (I've named your starting array a):

>>> b = a[np.argsort(a[:, 0])]
>>> grps, idx = np.unique(b[:, 0], return_index=True)
>>> counts = np.add.reduceat(b[:, 1:], idx)
>>> np.column_stack((grps, counts))
array([[117, 1, 1, 0, 0, 1],
[120, 0, 1, 1, 0, 0],
[163, 1, 0, 0, 0, 0],
[189, 0, 0, 0, 1, 0]])

This returns the rows in sorted order (by label).

A solution in pandas is possible in fewer lines (and potentially uses less additional memory than the NumPy method):

>>> df = pd.DataFrame(a)
>>> df.groupby(0, sort=False, as_index=False).sum().values
array([[117, 1, 1, 0, 0, 1],
[163, 1, 0, 0, 0, 0],
[120, 0, 1, 1, 0, 0],
[189, 0, 0, 0, 1, 0]])

The sort=False parameter means that the rows are returned in the order the unique labels were first encountered.

VBA consolidate duplicate values in a delimited array

I would suggest to use a dictionary for this, with the first 2 parts as key and the 3rd part (the number) as value.

Dim d As New Dictionary
Dim i As Long
For i = LBound(array1) to UBound(array1)
Dim tokens() As String, key, val As Long
tokens = Split(array1(i), ";")
key = tokens(0) & ";" & tokens(1)
val = CLng(tokens(2))

If d.Exists(key) Then
d(key) = d(key) + val
Else
d.Add key, val
End If
Next

For Each key In d.Keys()
Debug.Print key, d(key)
Next

Note that you either need to add a reference to the Microsoft Scripting Runtime or change the code to late binding.

Consolidate duplicate values of a certain key from an array of hashes into array

This works:

connections.group_by do |h| 
h[:name]
end.inject({}) do |h,(k,v)|
h.merge( { k => (v.map do |i| i[:number] end) } )
end
# => {"John Doe"=>["5551234567", "5559876543"], "Jane Doe"=>["5557654321"]}

Step by step...

connections is the same as in your post:

connections
# => [{:name=>"John Doe", :number=>"5551234567", :count=>8},
# {:name=>"Jane Doe", :number=>"5557654321", :count=>6}, {:name=>"John Doe",
# :number=>"5559876543", :count=>3}]

First we use group_by to combine the hash entries with the same :name:

connections.group_by do |h| h[:name] end
# => {"John Doe"=>[{:name=>"John Doe", :number=>"5551234567", :count=>8},
# {:name=>"John Doe", :number=>"5559876543", :count=>3}],
# "Jane Doe"=>[{:name=>"Jane Doe", :number=>"5557654321", :count=>6}]}

That's great, but we want the values of the result hash to be just the numbers that show up as values of the :number key, not the full original entry hashes.

Given just one of the list values, we can get the desired result this way:

[{:name=>"John Doe", :number=>"5551234567", :count=>8}, 
{:name=>"John Doe", :number=>"5559876543", :count=>3}].map do |i|
i[:number]
end
# => ["5551234567", "5559876543"]

But we want to do that to all of the list values at once, while keeping the association with their keys. It's basically a nested map operation, but the outer map runs across a Hash instead of an Array.

You can in fact do it with map. The only tricky part is that map on a Hash doesn't return a Hash, but an Array of nested [key,value] Arrays. By wrapping the call in a Hash[...] constructor, you can turn the result back into a Hash:

Hash[ 
connections.group_by do |h|
h[:name]
end.map do |k,v|
[ k, (v.map do |i| i[:number] end) ]
end
]

That returns the same result as my original full answer above, and is arguably clearer, so you might want to just use that version.

But the mechanism I used instead was inject. It's like map, but instead of just returning an Array of the return values from the block, it gives you full control over how the return value is constructed out of the individual block calls:

connections.group_by do |h| 
h[:name]
end.inject({}) do |h,(k,v)|
h.merge( { k => (v.map do |i| i[:number] end) } )
end

That creates a new Hash, which starts out empty (the {} passed to inject), and passes it to the do block (where it shows up as h) along with the first key/value pair in the Hash returned by group_by. That block creates another new Hash with the single key passed in and the result of transforming the value as we did above, and merges that into the passed-in one, returning the new value - basically, it adds one new key/value pair to the Hash, with the value transformed into the desired form by the inner map. The new Hash is returned from the block, so it becomes the new value of h for the next time through the block.

(We could also just assign the entry into h directly with h[k] = v.map ..., but the block would then need to return h afterward as a separate statement, since it is the return value of the block, and not the value of h at the end of the block's execution, that gets passed to the next iteration.)

As an aside: I used do...end instead of {...} around my blocks to avoid confusion with the {...} used for Hash literals. There is no semantic difference; it's purely a matter of style. In standard Ruby style, you would use {...} for single-line blocks, and restrict do...end to blocks that span more than one line.

Javascript: Merge Two Arrays of Objects, Only If Not Duplicate (Based on Specified Object Key)

You can create a set of IDs from initialData and this will make "check if ID is already in initial data" faster - O(1):

var initialData = [{    'ID': 1,    'FirstName': 'Sally'  },  {    'ID': 2,    'FirstName': 'Jim'  },  {    'ID': 3,    'FirstName': 'Bob'  }];
var newData = [{ 'ID': 2, 'FirstName': 'Jim' }, { 'ID': 4, 'FirstName': 'Tom' }, { 'ID': 5, 'FirstName': 'George' }];
var ids = new Set(initialData.map(d => d.ID));var merged = [...initialData, ...newData.filter(d => !ids.has(d.ID))];
console.log(merged);

Merge duplicate objects in array of objects

I would probably loop through with filter, keeping track of a map of objects I'd seen before, along these lines (edited to reflect your agreeing that yes, it makes sense to make (entry).data always an array):

var seen = {};
data = data.filter(function(entry) {
var previous;

// Have we seen this label before?
if (seen.hasOwnProperty(entry.label)) {
// Yes, grab it and add this data to it
previous = seen[entry.label];
previous.data.push(entry.data);

// Don't keep this entry, we've merged it into the previous one
return false;
}

// entry.data probably isn't an array; make it one for consistency
if (!Array.isArray(entry.data)) {
entry.data = [entry.data];
}

// Remember that we've seen it
seen[entry.label] = entry;

// Keep this one, we'll merge any others that match into it
return true;
});

In an ES6 environment, I'd use seen = new Map() rather than seen = {}.

Note: Array.isArray was defined by ES5, so some quite older browsers like IE8 won't have it. It can easily be shimmed/polyfilled, though:

if (!Array.isArray) {
Array.isArray = (function() {
var toString = Object.prototype.toString;
return function(a) {
return toString.call(a) === "[object Array]";
};
})();
}

Side note: I'd probably also always make entry.data an array, even if I didn't see two values for it, because consistent data structures are easier to deal with. I didn't do that above because your end result showed data being just a string when there was only one matching entry. (We've done that above now.)

Live example (ES5 version):

var data = [    {        label: "Book1",        data: "US edition"    },    {        label: "Book1",        data: "UK edition"    },    {        label: "Book2",        data: "CAN edition"    }];snippet.log("Before:");snippet.log(JSON.stringify(data, null, 2), "pre");var seen = {};data = data.filter(function(entry) {    var previous;
// Have we seen this label before? if (seen.hasOwnProperty(entry.label)) { // Yes, grab it and add this data to it previous = seen[entry.label]; previous.data.push(entry.data);
// Don't keep this entry, we've merged it into the previous one return false; }
// entry.data probably isn't an array; make it one for consistency if (!Array.isArray(entry.data)) { entry.data = [entry.data]; }
// Remember that we've seen it seen[entry.label] = entry;
// Keep this one, we'll merge any others that match into it return true;});snippet.log("After:");snippet.log(JSON.stringify(data, null, 2), "pre");
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --><script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>


Related Topics



Leave a reply



Submit