Increase count property on object if duplicate value exists in an array - javascript

I would like to take list variable and get it to the point that updated list is at but am unsure how.
const list = [{name:'apple'},{name:'apple'},{name:'banana'}];
const updatedList = [{name:'apple', count:2},{name:'banana', count: 1}];

Maybe this example will help you ?
const list = [{name:'apple'},{name:'apple'},{name:'banana'}];
const updatedList = Object.values(list.reduce(
(map, el) => {
map[el.name] ? map[el.name].count++ : map[el.name] = { ...el,
count: 1
};
return map;
}, {}
));
console.log(updatedList);

function uptadeLi(list,item,quant) {
// body...
for( i in list){
if (list[i].name === item){
list[i].count = quant
}
}
}
With that function you can set each one of the elements of lists , be sure to put the name of item as string

const list = [{name:'apple'},{name:'apple'},{name:'banana'}];
const res = list.reduce((sub,value)=>{
const index= sub.findIndex(i => i.name===value.name)
if(index !==-1)
sub[index].count++
else
sub.push({name:value.name,count:1})
return sub
},[])
console.log(res)

Use .reduce() method to evaluate the count for each item into an object with unique keys:
{ "apple": 2, "banana": 1 }
Then use Object.entries() to convert this into the following array:
[ ["apple", 2], ["banana", 1] ]
Finally, use .map() method to produce:
[ {"name": "apple", "count": 2}, {"name": "banana", "count": 1} ]
DEMO
const list = [{name:'apple'},{name:'apple'},{name:'banana'}];
const updatedList = Object.entries(
list.reduce(
(acc,cur) => ({...acc,[cur.name]:(acc[cur.name] || 0) + 1}),
{})
)
.map(([name,count]) => ({name,count}));
console.log( updatedList );

Related

Is there any other way to check multiple values are present in array of object?

I have the below array of objects and I want to check if two different users are present in this array .if present i have to run some logic
let result = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
var newArr = [];
var hasMatch = result.filter(function(val) {
if (val.name == "FGH"){
newArr.push(val)
} else if (val.name == "ABC") {
newArr.push(val)
}
});
console.log(newArr)
if (newArr.length == 2) {
//do logic
}
It's working as expected but I'm looking for a different approach for this. could someone advise?
Not optimized for speed, but does the job
let arr = [
{
"name": "ABC"
},
{
"name": "CDE"
},
{
"name": "FGH"
},
{
"name": "XYZ"
}
];
let users = ["ABC", "XYZ"]
let hasAllUsers = users.every(user => arr.some(item => item.name == user))
console.log(hasAllUsers)
// if(hasAllUser) {...}
It's a pretty roundabout way to zero in on the logic you're trying to express. Note how the result in hasMatch is never even used. That's really all you're looking for, does the array "have the values".
There's no need to push values to another array and check if that array has values. Just check of the original array has them.
Which could be as simple as:
let result = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
if (result.filter(r => r.name === "FGH" || r.name === "ABC").length === 2) {
// do logic
}
Or if you want to refactor the condition into a variable:
let result = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
let hasMatch = result.filter(r => r.name === "FGH" || r.name === "ABC").length === 2;
if (hasMatch) {
// do logic
}
Or a bit more verbose for clarity:
let result = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
let filteredResult = result.filter(r => r.name === "FGH" || r.name === "ABC");
let hasMatch = filteredResult.length === 2;
if (hasMatch) {
// do logic
}
You can simply create another array with the valid users and filter your array to match each items that are this array.
This can be done using the Array#includes method
const users = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
const validUsers = ["ABC", "FGH", "AnotherUser"];
const matchUsers = users.filter(user => validUsers.includes(user.name))
console.log(matchUsers)
You could count the wanted names.
const
data = [{ name: "ABC" }, { name: "CDE" }, { name: "FGH" }, { name: "XYZ" }],
names = ['ABC', 'FGH'],
result = data.reduce((t, { name }) => t + names.includes(name), 0);
console.log(result);
Try using a named function and pass in the array, key, and one or more values with the rest operator ...values. Use .flatMap() to filter with
[...values].includes(obj[key])
// ["ABC", "XYZ"].includes(obj.name)
and any non-match returns an empty array []. The final return is an array with a sub-array and the length of said sub-array.
const result = [["ABC", "XYZ"], 2]
// result[0][0] = "ABC"
// result[0][1] = "XYZ"
// result[1] = 2
const arr = [{"name": "ABC"},{"name": "CDE"},{"name": "FGH"},{"name": "XYZ"}];
function hasMatch(array, key, ...values) {
const result = array.flatMap((obj, idx) =>
[...values].includes(obj[key]) ? obj : []);
return [result, result.length];
}
console.log(hasMatch(arr, "name", "ABC", "XYZ"));
console.log(hasMatch(arr, "name", "FGH", "IJK", "LMN", "ABC", "XYZ"));

JS -Append key to matching array, object values

I would like to push key values to objects in array1 from other objects of array2
To do so it needs to search a corresponding values in both arrays, then push the right key.
let array1 = [
{
"Ref": "28189-060-B",
"Otherkey": "Whatever"
},
{
"Ref": "18182-250-B",
"Otherkey": "Whatever2"
},
{
"Ref": "55187-753-B",
"Otherkey": "Whatever3"
}
]
let array2 = [
{
"Ref": "28189-060-ABCD",
"Style": "Red"
},
{
"Ref": "18182-250-ABCD",
"Style": "Blue"
},
{
"Ref": "55187-753-ABCD",
"Style": "Yellow"
}
]
The function need to loop through all objects in array1, look at the first 9 characters of Ref values, find a match in array2 Ref (only first 9 characters are identical). When there is a match push the "Style" from array2 into the corresponding object in array1
I tried with Object.key.foreach(), map(), with substr to get only 9 characters, with find()... all of this has been a big mess and not working...
Expected result :
let array1 = [
{
"Ref": "18182-250-B",
"Otherkey": "Whatever2",
"Style": "Blue"
},
{
"Ref": "28189-060-B",
"Otherkey": "Whatever",
"Style": "Red"
},
{
"Ref": "55187-753-B",
"Otherkey": "Whatever3",
"Style": "Yellow"
}
]
Assuming those properties are all meant to be Ref (some are Global_Style), you can use forEach and find:
let array1 = [{"Ref":"28189-060-B","Otherkey":"Whatever"},{"Ref":"18182-250-B","Otherkey":"Whatever2"},{"Ref":"55187-753-B","Otherkey":"Whatever3"}];
let array2 = [{"Ref":"28189-060-ABCD","Style":"Red"},{"Ref":"18182-250-ABCD","Style":"Blue"},{"Ref":"55187-753-ABCD","Style":"Yellow"}];
const shorterRef = (ref) => ref.substr(0, 9);
array1.forEach(obj => {
const a1Ref = shorterRef(obj.Ref);
const arr2Obj = array2.find(tmp => shorterRef(tmp.Ref) === a1Ref);
if (arr2Obj) obj.Style = arr2Obj.Style;
});
console.log(array1);
If you didn't want to mutate the array go with map:
let array1 = [{"Ref":"28189-060-B","Otherkey":"Whatever"},{"Ref":"18182-250-B","Otherkey":"Whatever2"},{"Ref":"55187-753-B","Otherkey":"Whatever3"}];
let array2 = [{"Ref":"28189-060-ABCD","Style":"Red"},{"Ref":"18182-250-ABCD","Style":"Blue"},{"Ref":"55187-753-ABCD","Style":"Yellow"}];
const shorterRef = (ref) => ref.substr(0, 9);
const out = array1.map(obj => {
const a1Ref = shorterRef(obj.Ref);
const arr2Obj = array2.find(tmp => shorterRef(tmp.Ref) === a1Ref);
if (arr2Obj) return { ...obj, Style: arr2Obj.Style };
});
console.log(out);
var arrMap = {};
array1.forEach(function(x){
if(!arrMap[x.Ref.substring(0,9)]){
arrMap[x.Ref.substring(0,9)] = x;
}
});
array2.forEach(function(x){
if(Object.keys(arrMap).includes(x.Ref.substring(0,9))){
arrMap[x.Ref.substring(0,9)] = Object.assign(arrMap[x.Ref.substring(0,9)], {"Style": x.Style});
}
});
console.log(Object.values(arrMap));
Something like this may be what you want:
array1.forEach(function (element1) {
array2.forEach(function (element2){
addStyle(element1, element2);
});
});
function addStyle(obj1, obj2){
if (obj1.Ref && obj2.Ref){
let Ref1 = obj1.Ref.substr(0,8);
let Ref2 = obj2.Ref.substr(0, 8);
if (Ref1 === Ref2){
obj1.Style = obj2.Style;
};
}
}
So we loop through the fist array and for each item we loop through the second array.
Then we check if the expected fields are present and if so we compare them. If they match we add the "Style" field and move to the next object
The Below code will work although we might be able to optimize it further.
var newArr = []
for(let k in array1){
for(let i in array2){
console.log(array2[i]['Ref'].substr(0,9))
if(array1[k]['Ref'].substr(0,9) == array2[i]['Ref'].substr(0,9)){
let temp = array1[k]
temp['Style'] = array2[i]['Style']
newArr.push(temp)
}
}
}
The first solution is a bit complex.
You probable have a typo in array1 as your first key is not consistent. instead of Global_Stylecode you probably meant Ref, Anyway most likely it should have the same key. If we assume that the key is Ref, then
array1.forEach( ({Ref: Ref1, Otherkey}, index) => {
const Ref1Sub = Ref1.substring(0, 9);
array2.forEach(({Ref: Ref2, Style}) => {
if (Ref2.includes(Ref1Sub)) {
array1[index].Style = Style;
}
})
});
Also there is no need to define arrays as let. const will be fine.

Merge array with underscore by keys

I have 2 arrays :
[{id:1,name:"name"},{id:2,name:"name2"} ,{id:3,name:"name3"}]
[{id:1,date:"123"},{id:2,date:"456"}]
Array 1 should be updated only if the id is equal :
So the array 1 will looks like
It should not create a new array . Only update the array 1 based on array 2
[{id:1,name:"name",date:"123"},{id:2,name:"name2",date:"456"} ,{id:3,name:"name3"}]
I managed to do that with for loop on array2 and inside the for filter like the following :
._filter(array1,function(item){
If(item.id=array2.id)
Do smth and update the array1.date
})
How do I doing that in he best way ? Using underscore.js
You can do something like this:
Iterate over array1 and check if the id of each item exists in array2 by using the some() method.
var arr1 = [{id:1,name:"name"},{id:2,name:"name2"} ,{id:3,name:"name3"}];
var arr2 = [{id:1,date:"123"},{id:2,date:"456"}];
var missing = [];
arr1.forEach( (item1, i) => {
var isExist = arr2.some(item2 => item2.id === item1.id)
if(!isExist) {
missing.push(i);
}
})
missing.forEach(item => {
arr2.push(arr1[item]);
})
console.log(arr2);
reference for some()
Try this :
var a = [{id:1,name:"name"},{id:2,name:"name2"} ,{id:3,name:"name3"}] ;
var b = [{id:1,date:"123"},{id:2,date:"456"}] ;
var i = 0, j = 0 ;
while( i < a.length ) {
j = 0 ;
while( j < b.length) {
if ( a[i].id === b[j].id )
Object.assign( a[i] , b[j] );
j++;
}
i++;
}
console.log(a) ;
You can use forEach to iterate over the second array and use findIndex to get the matched element from first array. If the id matches then update the object in the first array
let arr1 = [{
id: 1,
name: "name"
}, {
id: 2,
name: "name2"
}, {
id: 3,
name: "name3"
}]
let arr2 = [{
id: 1,
date: "123"
}, {
id: 2,
date: "456"
}]
arr2.forEach(function(acc) {
let findArry1Index = arr1.findIndex(function(item) {
return item.id === acc.id;
});
if (findArry1Index !== -1) {
arr1[findArry1Index].date = acc.date;
}
});
console.log(arr1)
You can do it using native language like this:
const arr1 = [{id:1,name:"name"},{id:2,name:"name2"} ,{id:3,name:"name3"}];
const arr2 = [{id:1,date:"123"},{id:2,date:"456"}];
arr1.forEach((ele) => {
const match = arr2.find(item => ele.id === item.id) || {};
Object.assign(ele, match);
});
console.log(arr1);
var a = [{id:1,name:"name"},{id:2,name:"name2"} ,{id:3,name:"name3"}];
var b = [{id:1,date:"123"},{id:2,date:"456"}];
a = _.map(a, function(e) { return _.extend(e, _.findWhere(b, {id: e.id})); });
a results in:
0: {id: 1, name: "name", date: "123"}
1: {id: 2, name: "name2", date: "456"}
2: {id: 3, name: "name3"}
However, I guess this qualifies as "creating a new array"? Maybe it can serve as an inspiration though ¯\_(ツ)_/¯
You can use underscore's indexBy function to index your second array by id, and then simply use Object.assign(...) to update your first array's elements with their corresponding match by performing a lookup in the indexed elements object.
let arr1 = [{id:1, name:"name"}, {id:2, name:"name2"}, {id:3, name:"name3"}]
let arr2 = [{id:1, date:"123"}, {id:2, date:"456"}]
const arr2Groups = _.indexBy(arr2, e => e.id);
arr1.forEach(e => Object.assign(e, arr2Groups[e.id] || {}));
console.log(arr1);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>

Javascript how to join two arrays having same property value?

How do I join arrays with the same property value? I cannot map it because it has different indexes.
var array1 = [
{'label':"label1",'position':0},
{'label':"label3",'position':2},
{'label':"label2",'position':1},
];
var array2 = [
{'label':"label1",'value':"TEXT"},
{'label':"label2",'value':"SELECT"}
];
expected output:
var array3 = [
{'label':"label1",'value':"TEXT",'position':0},
{'label':"label2",'value':"SELECT", 'position':1}
];
This is what I did, I cannot make it work,
var arr3 = arr1.map(function(v, i) {
return {
"label": v.label,
"position": v.position,
"value": arr2[?].value
}
});
I think you can use array#reduce to do something like this perhaps:
var array1 = [
{'label':"label1",'position':0},
{'label':"label3",'position':2},
{'label':"label2",'position':1},
];
var array2 = [
{'label':"label1",'value':"TEXT"},
{'label':"label2",'value':"SELECT"}
];
var array3 = array2.reduce((arr, e) => {
arr.push(Object.assign({}, e, array1.find(a => a.label == e.label)))
return arr;
}, [])
console.log(array3);
You could take a Map and check the existence for a new object.
var array1 = [{ label: "label1", position: 0 }, { label: "label3", position: 2 }, { label: "label2", position: 1 }],
array2 = [{ label: "label1", value: "TEXT" }, { label: "label2", value: "SELECT" }],
map = array1.reduce((m, o) => m.set(o.label, o), new Map),
array3 = array2.reduce((r, o) => {
if (map.has(o.label)) {
r.push(Object.assign({}, o, map.get(o.label)));
}
return r;
}, []);
console.log(array3);
.as-console-wrapper { max-height: 100% !important; top: 0; }
As per the effort, we take an assumption that array1 will be having all the labels that are in array2.
Based on that first, create a map for array2and with key being labels. Post that, filter out array1 items which have labels existing in the map and then finally merging the objects of the filtered array and its corresponding values in map extracted from array2.
var array1 = [{'label':"label1",'position':0},{'label':"label3",'position':2},{'label':"label2",'position':1}];
var array2 = [{'label':"label1",'value':"TEXT"},{'label':"label2",'value':"SELECT"}];
let map = array2.reduce((a,{label, ...rest}) => Object.assign(a,{[label]:rest}),{});
let result = array1.filter(({label}) => map[label]).map(o => ({...o, ...map[o.label]}));
console.log(result);
Also, in the above snippet, you can improve the performance further by using Array.reduce against filter and map functions to retrieve the result.
var array1 = [{'label':"label1",'position':0},{'label':"label3",'position':2},{'label':"label2",'position':1}];
var array2 = [{'label':"label1",'value':"TEXT"},{'label':"label2",'value':"SELECT"}];
let map = array2.reduce((a,{label, ...rest}) => Object.assign(a,{[label]:rest}),{});
let result = array1.reduce((a,o) => {
if(map[o.label]) a.push({...o, ...map[o.label]});
return a;
}, []);
console.log(result);
If you don't know in advance which array(s) will have their labels be a subset of the other (if any), here's a method that allows for either array1 or array2 to have labels that the other array lacks. Use reduce over array1, finding the matching label in array2 if it exists:
var array1 = [
{'label':"label1",'position':0},
{'label':"label3",'position':2},
{'label':"label2",'position':1},
];
var array2 = [
{'label':"label1",'value':"TEXT"},
{'label':"label2",'value':"SELECT"}
];
const output = array1.reduce((a, { label, position }) => {
const foundValueObj = array2.find(({ label: findLabel }) => findLabel === label);
if (!foundValueObj) return a;
const { value } = foundValueObj;
a.push({ label, value, position });
return a;
}, []);
console.log(output);
See Array.prototype.map() and Map for more info.
// Input.
const A = [{'label':"label1",'position':0},{'label':"label3",'position':2},{'label':"label2",'position':1}]
const B = [{'label':"label1",'value':"TEXT"},{'label':"label2",'value':"SELECT"}]
// Merge Union.
const mergeUnion = (A, B) => {
const mapA = new Map(A.map(x => [x.label, x]))
return B.map(y => ({...mapA.get(y.label), ...y}))
}
// Output + Proof.
const output = mergeUnion(A, B)
console.log(output)
This works.
Approach: Concatenate the objects with same label, using Object.assign()
var array1 = [{'label':"label1",'position':0},{'label':"label3",'position':2},{'label':"label2",'position':1}];
var array2 = [{'label':"label1",'value':"TEXT"},{'label':"label2",'value':"SELECT"}];
var result = [];
array2.forEach(function(value, index){
result.push(Object.assign({},array1.find(function(v,i){return v.label==value.label}),value));
});
console.log(result)
Im not good with javascript,but you could also do this
var array1 = [
{'label':"label1",'position':0},
{'label':"label3",'position':2},
{'label':"label2",'position':1},
];
var array2 = [
{'label':"label1",'value':"TEXT"},
{'label':"label2",'value':"SELECT"}
];
var array3=[];
for(var i=0;i<array1.length;i++)
{
for(var x=0;x<array2.length;x++)
{
console.log(array1[i]['label'] == array2[x]['label']);
if(array1[i]['label'] == array2[x]['label']){
array3.push({label:array1[i]['label'],value:array2[x]['value'],position:array1[i]['position']});
}
}
}
console.log(array3);

array map, map array as a key of an array

I know the title might sounds confusing, but i'm stuck for an hour using $.each. Basically I have 2 arrays
[{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
and [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
How do I put one into another as a new property key like
[{
"section_name": "abc",
"id": 1,
"new_property_name": [{
"toy": "car"
}, {
"tool": "knife"
}]
}, {
"section_name": "xyz",
"id": 2,
"new_property_name": [{
"weapon": "cutter"
}]
}]
ES6 Solution :
const arr = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
const arr2 = [{"toy":"car","id":1},{"tool":"knife","id":1},{"weapons":"cutter","id":2}];
const res = arr.map((section,index) => {
section.new_property_name = arr2.filter(item => item.id === section.id);
return section;
});
EDIT : Like georg mentionned in the comments, the solution above is actually mutating arr, it modifies the original arr (if you log the arr after mapping it, you will see it has changed, mutated the arr and have the new_property_name). It makes the .map() useless, a simple forEach() is indeed more appropriate and save one line.
arr.forEach(section => {
section.new_property_name = arr2.filter(item => item.id === section.id));
});
try this
var data1 = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
var data2 = [{"toy":"car","id":1},{"tool":"knife","id":1},{"weapons":"cutter","id":2}];
var map = {};
//first iterate data1 the create a map of all the objects by its ids
data1.forEach( function( obj ){ map[ obj.id ] = obj });
//Iterate data2 and populate the new_property_name of all the ids
data2.forEach( function(obj){
var id = obj.id;
map[ id ].new_property_name = map[ id ].new_property_name || [];
delete obj.id;
map[ id ].new_property_name.push( obj );
});
//just get only the values from the map
var output = Object.keys(map).map(function(key){ return map[ key ] });
console.log(output);
You could use ah hash table for look up and build a new object for inserting into the new_property_name array.
var array1 = [{ "section_name": "abc", "id": 1 }, { "section_name": "xyz", "id": 2 }],
array2 = [{ "toy": "car", "section_id": 1 }, { "tool": "knife", "section_id": 1 }, { "weapons": "cutter", "section_id": 2 }],
hash = Object.create(null);
array1.forEach(function (a) {
a.new_property_name = [];
hash[a.id] = a;
});
array2.forEach(function (a) {
hash[a.section_id].new_property_name.push(Object.keys(a).reduce(function (r, k) {
if (k !== 'section_id') {
r[k] = a[k];
}
return r;
}, {}));
});
console.log(array1);
Seems like by using Jquery $.merge() Function you can achieve what you need. Then we have concat function too which can be used to merge one array with another.
Use Object.assign()
In your case you can do it like Object.assign(array1[0], array2[0]).
It's very good for combining objects, so in your case you just need to combine your objects within the array.
Example of code:
var objA = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
var objB = [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
var objC = Object.assign({},objA[0],objB[0]);
console.log(JSON.stringify(objC));// {"section_name":"abc","id":1,"toy":"car","section_id":1}
For more info, you can refer here: Object.assign()
var firstArray = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}],
secondArray = [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
var hash = Object.create(null);
firstArray.forEach(s => {
hash[s.id] = s;
s['new_property_name'] = [];
});
secondArray.forEach(i => hash[i['section_id']]['new_property_name'].push(i));
console.log(firstArray);

Categories