Sort big array into smaller by value in objects - javascript

I have large array, which looks like this:
let arr = [{
'name': '1',
'val': '12'
},{
'name': '4',
'val': '52'
},
{
'name': '11',
'val': '15'
},
{
'name': '4',
'val': '33'
},
...]
I want find all objects with same name values and push them into separated arrays .
P.S. I don't know possible name values in array.

You can easily group by name to get what you need. Below is a quite general function to group any array of objects to a Map, by specified property. Then simply make it an array and you're done
function group(arr, propertyToGroupBy) {
return arr.reduce(function(a, b) {
return a.set(b[propertyToGroupBy], (a.get(b[propertyToGroupBy]) || []).concat(b));
}, new Map);
}
const map = group(arr, 'name');
console.log(Array.from(map));
<script>
let arr = [{
'name': '1',
'val': '12'
}, {
'name': '4',
'val': '52'
},
{
'name': '11',
'val': '15'
},
{
'name': '4',
'val': '33'
}
];
</script>

You can group your array based on name in an object accumulator. Then using Object.values() you can get all the values.
let arr = [{ 'name': '1', 'val': '12' },{ 'name': '4', 'val': '52' }, { 'name': '11', 'val': '15' }, { 'name': '4', 'val': '33' }],
result = Object.values(arr.reduce((r,o) => {
r[o.name] = r[o.name] || [];
r[o.name].push(o);
return r;
},{}));
console.log(result);

let arr=[{'name':'1','val':'12'},{'name':'4','val':'52'},{'name':'11','val':'15'},{'name':'4','val':'33'}];
let groups = arr.reduce((obj, el) => ({...obj, [el.name]: [...obj[el.name] || [], el] }), {});
console.log(groups);

Group with reduce and map out the output to be an array:
let arr = [{'name': '1','val': '12'},{'name': '4','val': '52'}, {'name': '11','val': '15'},{'name': '4','val': '33'}];
// group object by same name
const dataObj = arr.reduce((all, {name, val}) => {
if (!all.hasOwnProperty(name)) all[name] = [];
all[name].push({name, val});
return all;
}, {});
// map out the result into an array
const result = Object.keys(dataObj).map(k => (dataObj[k]));
console.log(result);

Related

How to merge two different array of object in JavaScript? Check below example

Input Arrays:
var array1 = [
{
PersonalID: '11',
qusetionNumber: '1',
value: 'Something'
},
{
PersonalID: '12',
qusetionNumber: '2',
value: 'whatever'
},
];
var array2 = [
{
uniqueId: '111'
},
{
uniqueId: '222'
},
];
Result:
var results = [
{
PersonalID: '11',
qusetionNumber: '1',
value: 'Something',
uniqueId: '111'
},
{
PersonalID: '12',
qusetionNumber: '2',
value: 'whatever',
uniqueId: '222'
},
];
There are a few ways to do this, perhaps this is acceptable? Simply looping over the first array and using the index to select the correct object from the second array.
var array1 = [
{
PersonalID: '11',
qusetionNumber: '1',
value: 'Something'
},
{
PersonalID: '12',
qusetionNumber: '2',
value: 'whatever'
},
];
var array2 = [
{
uniqueId: '111'
},
{
uniqueId: '222'
},
];
var result = [];
array1.forEach((itm, idx, _) => {
result.push({ ...itm, ...array2[idx] });
});
console.log(result)
You can use Array.map() along with spread syntax (...) to merge the values from the two arrays.
const array1 = [ { PersonalID: '11', qusetionNumber: '1', value: 'Something' }, { PersonalID: '12', qusetionNumber: '2', value: 'whatever' }, ];
const array2 = [ { uniqueId: '111' }, { uniqueId: '222' }, ];
const result = array1.map((el, idx) => ({ ...el, ...array2[idx]}));
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }
In addition to the already provided approaches one also could implement callback functions for ...
a map based approach where the callback utilizes the map methods 2nd thisArg parameter for providing the 2nd array (the OP's array2).
a reduce based approach where the callback gets the 2nd array (the OP's array2) provided as property of the reduce methods 2nd parameter, its initial value.
In both cases Object.assign is one possible way of creating a merged object which is loosely decoupled from both of its source items.
Unlike all the other so far provided solutions both suggested ways have in common that each implementation is agnostic to the OP's outer-scope array-references. And due to being provided as function statements the code is re-usable as well.
const array1 = [{
PersonalID: '11',
qusetionNumber: '1',
value: 'Something'
}, {
PersonalID: '12',
qusetionNumber: '2',
value: 'whatever'
}];
const array2 = [{
uniqueId: '111'
}, {
uniqueId: '222'
}];
function mergeWithBoundArraysRelatedItem(item, idx) {
return Object.assign({}, item, this[idx]);
}
console.log(
'`map` based ...\n\n',
'array1.map(mergeWithBoundArraysRelatedItem, array2) =>',
array1
.map(mergeWithBoundArraysRelatedItem, array2)
);
function mergeRelatedArrayItems({ result, source }, item, idx) {
result.push(
Object.assign({}, item, source[idx])
);
return { result, source };
}
console.log(
'`reduce` based ...\n\n',
'array1.reduce(mergeRelatedArrayItems, { source: array2, result: [] }).result =>',
array1
.reduce(mergeRelatedArrayItems, {
source: array2, result: [],
})
.result
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
var array1 = [
{
PersonalID: '11',
qusetionNumber: '1',
value: 'Something'
},
{
PersonalID: '12',
qusetionNumber: '2',
value: 'whatever'
},
];
var array2 = [
{
uniqueId: '111'
},
{
uniqueId: '222'
},
];
const fun =(ar , ar2)=>{
for(let [k , v] of Object.entries(ar2)){
for(x in v){
ar[k][x] = v[x]
}
}
return ar
}
console.log(fun(array1 , array2))
var array1 = [
{
PersonalID: '11',
qusetionNumber: '1',
value: 'Something'
},
{
PersonalID: '12',
qusetionNumber: '2',
value: 'whatever'
},
];
var array2 = [
{
uniqueId: '111'
},
{
uniqueId: '222'
},
];
// if you don't want array1 to be modified use instead
// Array.from(array1).map(function(e,i){return Object.assign(e,array2[i])})
array1.map(function(e,i){return Object.assign(e,array2[i])})
console.log(array1)
I can also use Object.assign
var array1 = [{
PersonalID: '11',
qusetionNumber: '1',
value: 'Something'
},
{
PersonalID: '12',
qusetionNumber: '2',
value: 'whatever'
},
];
var array2 = [{
uniqueId: '111'
},
{
uniqueId: '222'
},
];
let myArr = []
for(let i = 0 ; i<array1.length ; i++){
myArr.push(Object.assign(array1[i], array2[i]))
}
console.log(myArr)

Lodash - Merge object from another array with same key as sub object to main array

const _ = require('lodash');
const parentDetails = [
{
'name': '5003',
'id': '1'
},
{
'name': '5000',
'id': '2'
}
];
const childrenDetails = [
{
'cid': '11',
'Reference': '5003'
},
{
'cid': '22',
'Reference': '5000'
}
];
Desired Output using lodash library: Extract matching reference from the second array with the name of the first array and append the matching child detail as an object to the first array as shown below. The result should not mutate the original array.
result = [
{
'name': '5003',
'id': '1',
'childrenDetail' : {
'cid': '11',
'Reference': '5003'
}
},
{
'name': '5000',
'id': '2',
'childrenDetail' : {
'cid': '22',
'Reference': '5000'
}
}
];
Here is an example using _.find()
const result = parentDetails.map(elm => {
const childrenDetail = _.find(childrenDetails, elm2 => elm2.Reference === elm.name);
if (childrenDetail) return ({...elm, childrenDetail});
});
console.log(result);
You can also replace array.map() with _.map().

Find object in array ids

I've list of id's in array and list of article in other array.
I would like filter my article array by ids find in id's array.
Exemple :
const ids = [ '1', '2', '3' ];
const articles = [
{ id: '1', title: 'blua' },
{ id: '10', title: 'blua' }
...
];
I've try this :
ids.map((id) => {
return audits.find((audit) => {
return id === audit.id;
});
});
But return underfined :/
I think it's not a good methode ^^
Anyone can help me ?
Thank you !
Use array.prototype.filter and array.prototype.includes:
const ids = [ '1', '2', '3' ];
const articles = [ { id: '1', title: 'blua' },{ id: '10', title: 'blua' } ];
const filtered = articles.filter(a => ids.includes(a.id));
console.log(filtered);
const ids = [ '1', '2', '3' ];
const articles = [
{ id: '1', title: 'blua' },
{ id: '10', title: 'blua' }
...
];
let results = articles.filter( (a) => ids.indexOf(a.id) !== -1);

how to pivot using javascritpt?

I'm facing an array of objects where it is possible to have more than one object with the same value of id. When the value of id is the same, the value of price will also be the same.
Here's an example:
[{
'id': 'A', 'price': 1, 'quantity': 1
}, {
'id': 'A', 'price': 1, 'quantity': 2
}, {
'id': 'B', 'price': 1, 'quantity': 1
}]
The result should be an array where only one object appears for every id. Moreover, quantity must be populated with the sum of the quantities in the repeated values of id.
Here's the expected result for the example above:
[{
'id': 'A','price': 1, 'quantity': 3
}, {
'id': 'B','price': 1, 'quantity': 1
}]
Actually, I need to pivot.
I would like to avoid jQuery and external calls. Is it possible to accomplish this using only JS functions?
Arrays of objects are a little messy to work with, but this is do-able.
const list = [
{'id': 'A', 'price': 1, 'quantity': 1},
{'id': 'A', 'price': 1, 'quantity': 2},
{'id': 'B', 'price': 1, 'quantity': 1}
];
// Objects are easier to work with. An intermediate step to combine entries by Id.
const intermediate = list.reduce((a, { id, price, quantity }) => {
a[id] = a[id] || { id, price, quantity: 0}; // Copy id & price if the entry doesn't exist yet.
a[id].quantity += quantity; // Add quantity.
return a;
}, {});
// Map it all back to an array of objects.
const result = Object.keys(intermediate).map(id => intermediate[id]);
console.log(result);
Here's a ES5 version:
var list = [
{'id': 'A', 'price': 1, 'quantity': 1},
{'id': 'A', 'price': 1, 'quantity': 2},
{'id': 'B', 'price': 1, 'quantity': 1}
];
// Objects are easier to work with. An intermediate step to combine entries by Id.
var intermediate = list.reduce(function(a, curr) {
a[curr.id] = a[curr.id] || { id: curr.id, price: curr.price, quantity: 0}; // Copy id & price if the entry doesn't exist yet.
a[curr.id].quantity += curr.quantity; // Add quantity.
return a;
}, {});
// Map it all back to an array of objects.
var result = Object.keys(intermediate).map(function(id){
return intermediate[id];
});
console.log(result);
You can try this code, it's very simple to understand:
var objs = [
{ 'id': 'A', 'price': 1, 'quantity': 1 },
{ 'id': 'A', 'price': 1, 'quantity': 2 },
{ 'id': 'B', 'price': 1, 'quantity': 1 }
];
const results = objs.reduce(function(acc, current) {
var obj = acc.find(function(o) {
return o.id === current.id && o.price === current.price
});
if (obj) {
obj.quantity += current.quantity;
} else {
acc.push(current);
}
return acc;
}, []);
console.log(results);
maybe not efficient, but does its work.
const array = [{
'id': 'A', 'price': 1, 'quantity': 1
},{
'id': 'A', 'price': 1, 'quantity': 2
},{
'id': 'B', 'price': 1, 'quantity': 1
}];
const aggregated = array.reduce(function (p, c) {
if (!p[c.id]) p[c.id] = {quantity: c.quantity, id: c.id, price: c.price};
else p[c.id].quantity += c.quantity;
return p;
}, {});
const final = Object.keys(aggregated).map(function(k) { return aggregated[k]; });
console.log(final);

ImmutableJS: merge two list of objects, without duplicating them

Supposing I have the below:
var allFoods = Immutable.List();
var frenchFood = Immutable.List([
{
'type': 'french fries',
'price': 3
},
{
'type': 'petit gateau',
'price': 40
},
{
'type': 'croissant',
'price': 20
},
]);
var fastFood = Immutable.List([
{
'type': 'cheeseburger',
'price': 5
},
{
'type': 'vegan burger',
'price': 20
},
{
'type': 'french fries',
'price': 3
}
]);
I want to merge both lists, in a way that I also remove dupes (in this case, french fries), so the expected result would be:
{
'type': 'french fries', // keep the first french fries
'price': 3
},
{
'type': 'petit gateau',
'price': 40
},
{
'type': 'croissant',
'price': 20
},
{
'type': 'cheeseburger',
'price': 5
},
{
'type': 'vegan burger',
'price': 20
}
What I'm trying (doesn't remove dupes):
allFoods = frenchFood.concat(fastFood);
allFoods = allFoods.filter(function(item, pos) {
return allFoods.indexOf(item) === pos;
});
Which returns arrays merged, but still duplicated.
What am I missing?
const allFoods = frenchFood.concat(fastFood.filter((item) =>
frenchFood.indexOf(item) < 0
));
I would use reduce
var result = frenchFood.concat(fastFood).reduce( (reduction, food) => {
if(reduction[food.type]) {
return reduction;
} else {
return reduction.set([food.type], food);
}
}, new Immutable.Map()).valueSeq().toList();
I would highly encourage you to not nest js objects inside immutable structures. Better to wrap those objects in an Immutable.Map() or do Immutable.fromJS(yourJsObj).
Least amount of code
const results = Immutable.Set(frenchFood).union(Immutable.Set(fastFood));
However #rooftop answer fastest
https://jsperf.com/union-vs-concat-immutable
I found a best solution (for me) on medium, link to origin answer is dead: https://medium.com/#justintulk/merging-and-deduplicating-data-arrays-with-array-reduce-efaa4d7ef7b0
const arr1 = [
{ id: 1, name: 'Array 1-1' },
{ id: 2, name: 'Array 1-2' },
{ id: 3, name: 'Array 1-3' }
]
const arr2 = [
{ id: 1, name: 'Array 2-1' },
{ id: 3, name: 'Array 2-3' },
{ id: 4, name: 'Array 2-4' }
]
const mergeArrObjectsUnique = (currentArr, newArr) => {
let obj = {}
currentArr.forEach(item => {
obj[item.id] = item
})
newArr.forEach(item => {
obj[item.id] = item
})
let result = [];
for(let p in obj) {
if(obj.hasOwnProperty(p))
result.push(obj[p])
}
console.log('result: ', result)
return result
}
mergeArrObjectsUnique(arr1, arr2)

Categories

Resources