Get data from javascript array - javascript

I have this array of objects:
var frequencies = [{id:124,name:'qqq'},
{id:589,name:'www'},
{id:45,name:'eee'},
{id:567,name:'rrr'}];
And this array of id:
var idArray = [124,45];
I need create function that return array of string that contains value of the name that has idArray.
for example, the result according to the arrays above(frequencies and idArray) :
var result = var frequencies = ['qqq','eee'];
How can I implement this function?

Use Array#filter and Array#map methods.
var res = frequencies
//filter out object array
.filter(function(v) {
return idArray.indexOf(v.id) > -1;
})
// generate result arrray from filtered array
.map(function(v) {
return v.name
});
var frequencies = [{
id: 124,
name: 'qqq'
}, {
id: 589,
name: 'www'
}, {
id: 45,
name: 'eee'
}, {
id: 567,
name: 'rrr'
}];
var idArray = [124, 45];
var res = frequencies
//filter out object array
.filter(function(v) {
return idArray.indexOf(v.id) > -1;
})
// generate result arrray from filtered array
.map(function(v) {
return v.name
});
// with ES6 arrow function
//var res = frequencies.filter(v => idArray.indexOf(v.id) > -1).map(v => v.name);
console.log(res);
The same code with ES6 arrow function.
var res = frequencies
.filter(v => idArray.indexOf(v.id) > -1)
.map(v => v.name);
var frequencies = [{
id: 124,
name: 'qqq'
}, {
id: 589,
name: 'www'
}, {
id: 45,
name: 'eee'
}, {
id: 567,
name: 'rrr'
}];
var idArray = [124, 45];
var res = frequencies
.filter(v => idArray.indexOf(v.id) > -1)
.map(v => v.name);
console.log(res);
Or use a simple for loop
var res = [];
for (var i = 0; i < frequencies.length; i++) {
// check the id value present in array
// push the name property value if id present in array
if (idArray.indexOf(frequencies[i].id) > -1) {
res.push(frequencies[i].name);
}
}
var frequencies = [{
id: 124,
name: 'qqq'
}, {
id: 589,
name: 'www'
}, {
id: 45,
name: 'eee'
}, {
id: 567,
name: 'rrr'
}];
var idArray = [124, 45],
res = [];
for (var i = 0; i < frequencies.length; i++) {
// check the id value present in array
// push the name property value if id present in array
if (idArray.indexOf(frequencies[i].id) > -1) {
res.push(frequencies[i].name);
}
}
console.log(res);

ESNEXT code
frequencies
.filter(({id}) => idArray.includes(id))
.map(({name}) => name)

Related

Sum values depending on other value in array

I have an array of objects that represent transactions of shares:
[{
date : ...,
symbol: 'TSLA',
amount: 3,
price: 1000.00
},
{
date : ...,
symbol: 'AAPL',
amount: 1,
price: 1200.00
},
{
date : ...,
symbol: 'AAPL',
amount: 7,
price: 1300.00
}]
I need to get sum of amounts based of symbol of that array, so output would be:
[{
symbol: 'TSLA',
amount: 3,
},
{
symbol: 'AAPL',
amount: 8,
}]
Is there an efficient way to do this with build in operations in javascript, or is the only way to do it with 2 array and double loop?
I was thinking of saving symbols in separate Set, and then suming all amounts, but is there a better way?
I've tried this, but this seems to only copy the original array.
const checkIfExists = (array, value) => {
array.forEach((el, i) => {
if (el.symbol === value) {
return i;
}
});
return -1;
};
const calculateSameValues = (data) => {
let result = [];
data.forEach((el) => {
const index = checkIfExists(result, el.symbol);
if (index === -1) {
result.push({symbol: el.symbol, amount: el.amount});
} else result[index].amount += el.amount;
});
console.log(result);
};
Seems like my checkIfExists function was returning always -1.
I fixed it by saving index in seperate variable and than returning it.
Here's code:
const checkIfExists = (array, value) => {
let index = -1;
array.forEach((el, i) => {
if (el.symbol === value) {
console.log(i);
index = i;
}
});
return index;
};
Note that this still uses 2 loops, I was looking for something more efficient, but this works.
you can use array.reduce() something like this:
const arr = [{
symbol: 'TSLA',
amount: 3,
price: 1000.00
},
{
symbol: 'AAPL',
amount: 1,
price: 1200.00
},
{
symbol: 'AAPL',
amount: 7,
price: 1300.00
}]
const x = arr.reduce(function(acc, cur) {
const idx = acc.findIndex(el => el.symbol === cur.symbol);
const obj = {
symbol: cur.symbol,
amount: cur.amount,
}
if(idx < 0) {
acc.push(obj)
} else {
acc[idx].amount = acc[idx].amount + cur.amount;
}
return acc;
}, []);
console.log(x);

Get list of duplicate objects in an array of objects

I am trying to get duplicate objects within an array of objects. Let's say the object is like below.
values = [
{ id: 10, name: 'someName1' },
{ id: 10, name: 'someName2' },
{ id: 11, name: 'someName3' },
{ id: 12, name: 'someName4' }
];
Duplicate objects should return like below:
duplicate = [
{ id: 10, name: 'someName1' },
{ id: 10, name: 'someName2' }
];
You can use Array#reduce to make a counter lookup table based on the id key, then use Array#filter to remove any items that appeared only once in the lookup table. Time complexity is O(n).
const values = [{id: 10, name: 'someName1'}, {id: 10, name: 'someName2'}, {id: 11, name:'someName3'}, {id: 12, name: 'someName4'}];
const lookup = values.reduce((a, e) => {
a[e.id] = ++a[e.id] || 0;
return a;
}, {});
console.log(values.filter(e => lookup[e.id]));
Let's say you have:
arr = [
{ id:10, name: 'someName1' },
{ id:10, name: 'someName2' },
{ id:11, name: 'someName3' },
{ id:12, name: 'someName4' }
]
So, to get unique items:
unique = arr
.map(e => e['id'])
.map((e, i, final) => final.indexOf(e) === i && i)
.filter(obj=> arr[obj])
.map(e => arr[e]);
Then, result will be
unique = [
{ id:10, name: 'someName1' },
{ id:11, name: 'someName3' },
{ id:12, name: 'someName4' }
]
And, to get duplicate ids:
duplicateIds = arr
.map(e => e['id'])
.map((e, i, final) => final.indexOf(e) !== i && i)
.filter(obj=> arr[obj])
.map(e => arr[e]["id"])
List of IDs will be
duplicateIds = [10]
Thus, to get duplicates objects:
duplicate = arr.filter(obj=> dublicateIds.includes(obj.id));
Now you have it:
duplicate = [
{ id:10, name: 'someName1' },
{ id:10, name: 'someName2' }
]
Thanks https://reactgo.com/removeduplicateobjects/
You haven't clarified whether two objects with different ids, but the same "name" count as a duplicate. I will assume those do not count as a duplicate; in other words, only objects with the same id will count as duplicate.
let ids = {};
let dups = [];
values.forEach((val)=> {
if (ids[val.id]) {
// we have already found this same id
dups.push(val)
} else {
ids[val.id] = true;
}
})
return dups;
With lodash you can solve this with filter and countBy for complexity of O(n):
const data = [{ id: 10,name: 'someName1' }, { id: 10,name: 'someName2' }, { id: 11,name: 'someName3' }, { id: 12,name: 'someName4' } ]
const counts = _.countBy(data, 'id')
console.log(_.filter(data, x => counts[x.id] > 1))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
You could do the same with ES6 like so:
const data = [{ id: 10,name: 'someName1' }, { id: 10,name: 'someName2' }, { id: 11,name: 'someName3' }, { id: 12,name: 'someName4' } ]
const countBy = (d, id) => d.reduce((r,{id},i,a) => (r[id] = a.filter(x => x.id == id).length, r),{})
const counts = countBy(data, 'id')
console.log(data.filter(x => [x.id] > 1))
You can use an array to store unique elements and use filter on values to only return duplicates.
const unique = []
const duplicates = values.filter(o => {
if(unique.find(i => i.id === o.id && i.name === o.name)) {
return true
}
unique.push(o)
return false;
})
With lodash you can use _.groupBy() to group elements by their id. Than _.filter() out groups that have less than two members, and _.flatten() the results:
const values = [{id: 10, name: 'someName1'}, {id: 10, name: 'someName2'}, {id: 11, name:'someName3'}, {id: 12, name: 'someName4'}];
const result = _.flow([
arr => _.groupBy(arr, 'id'), // group elements by id
g => _.filter(g, o => o.length > 1), // remove groups that have less than two members
_.flatten // flatten the results to a single array
])(values);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
An alternative based in #ggorlen solution with new Map() as accumulator (for better performance) and without unary operator ++ (not advised by default in projects with ESLint).
const values = [{ id: 10, name: "someName1" }, { id: 10, name: "someName2" }, { id: 11, name: "someName3" }, { id: 12, name: "someName4" },];
const lookup = values.reduce((a, e) => {
a.set(e.id, (a.get(e.id) ?? 0) + 1);
return a;
}, new Map());
console.log(values.filter(e => lookup.get(e.id) > 1));
Try this
function checkDuplicateInObject(propertyName, inputArray) {
var seenDuplicate = false,
testObject = {};
inputArray.map(function(item) {
var itemPropertyName = item[propertyName];
if (itemPropertyName in testObject) {
testObject[itemPropertyName].duplicate = true;
item.duplicate = true;
seenDuplicate = true;
}
else {
testObject[itemPropertyName] = item;
delete item.duplicate;
}
});
return seenDuplicate;
}
referred from : http://www.competa.com/blog/lets-find-duplicate-property-values-in-an-array-of-objects-in-javascript/

combine array of objects by key

I am trying to combine/merge 2 array of objects by key in my case id.
Objective:
I am expecting a results where I would have array containing all objects with ids 1,2,3,4 as per example
Order of merging should not affect number of objects in result for example combine(arr1,arr2) or combine(arr2,arr1) should have array with same number of objects
Order of merging can only affect resulting object for example in case of combine(arr1,arr2) arr2 key,values pair can override arr1 key,values just like deep jquery extend $.extend( true, arr1ObJ,arr2ObJ );
JSFIDDLE: https://jsfiddle.net/bababalcksheep/u2c05nyj/
Sample Data:
var arr1 = [{
id: 1,
name: "fred",
title: "boss"
}, {
id: 2,
name: "jim",
title: "nobody"
}, {
id: 3,
name: "bob",
title: "dancer"
}];
var arr2 = [{
id: 1,
wage: "300",
rate: "day"
}, {
id: 2,
wage: "10",
rate: "hour"
}, {
id: 4,
wage: "500",
rate: "week"
}];
var Result = [{
"id": 1,
"name": "fred",
"title": "boss",
"wage": "300",
"rate": "day"
}, {
"id": 2,
"name": "jim",
"title": "nobody",
"wage": "10",
"rate": "hour"
}, {
id: 3,
name: "bob",
title: "dancer"
}, {
id: 4,
wage: "500",
rate: "week"
}];
Here's a solution. It basically goes through each element of arr2 and checks to see if there's an element with a matching ID arr1. If so, it updates the matching element in arr1 with arr2's values. If there is no match, it simply pushes the element in arr2 onto arr1.
var arr1 = [{id: 1,name: 'fred',title: 'boss'},
{id: 2,name: 'jim',title: 'nobody'},
{id: 3,name: 'bob',title: 'dancer'}];
var arr2 = [{id: 1,wage: '300',rate: 'day'},
{id: 2,wage: '10',rate:'hour'},
{id: 4,wage: '500',rate: 'week'}];
function combineArrays(arr1, arr2) {
for(var i = 0; i < arr2.length; i++) {
// check if current object exists in arr1
var idIndex = hasID(arr2[i]['id'], arr1);
if(idIndex >= 0){
//update
for(var key in arr2[i]){
arr1[idIndex][key] = arr2[i][key];
}
} else {
//insert
arr1.push(arr2[i]);
}
}
return arr1;
}
//Returns position in array that ID exists
function hasID(id, arr) {
for(var i = 0; i < arr.length; i ++) {
if(arr[i]['id'] === id)
{
return i;
}
}
return -1;
}
var combine = combineArrays(arr1, arr2);
output(combine);
/* pretty Print */
function output(inp) {
var str = JSON.stringify(inp, undefined, 4);
$('body').append($('<pre/>').html(str));
}
var arr1 = [{
id: 1,
name: 'fred',
title: 'boss'
}, {
id: 2,
name: 'jim',
title: 'nobody'
}, {
id: 3,
name: 'bob',
title: 'dancer'
}];
var arr2 = [{
id: 1,
wage: '300',
rate: 'day'
}, {
id: 2,
wage: '10',
rate: 'hour'
}, {
id: 4,
wage: '500',
rate: 'week'
}];
function combineArrays(arr1, arr2) {
for (var i = 0; i < arr2.length; i++) {
var idIndex = hasID(arr2[i]['id'], arr1);
if (idIndex >= 0) {
for (var key in arr2[i]) {
arr1[idIndex][key] = arr2[i][key];
}
} else {
arr1.push(arr2[i]);
}
}
return arr1;
}
function hasID(id, arr) {
for (var i = 0; i < arr.length; i++) {
if (arr[i]['id'] === id) {
return i;
}
}
return -1;
}
var combine = combineArrays(arr1, arr2);
output(combine);
/* pretty Print */
function output(inp) {
var str = JSON.stringify(inp, undefined, 4);
$('body').append($('<pre/>').html(str));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
How about something along the lines of this:
function combineArrays(arr1, arr2, keyFunc) {
var combined = [],
keys1 = arr1.map(keyFunc),
keys2 = arr2.map(keyFunc),
pos1 = keys1.map(function (id) {
return keys2.indexOf(id);
}),
pos2 = keys2.map(function (id) {
return keys1.indexOf(id);
});
arr1.forEach(function (item, i) {
combined.push( $.extend(item, arr2[pos1[i]]) );
});
arr2.forEach(function (item, i) {
if (pos2[i] === -1) combined.push( item );
});
return combined;
}
used as
var combine = combineArrays(arr1, arr2, function (item) {
return item.id;
});
var arr1 = [
{ id: 1, name: 'fred', title: 'boss' },
{ id: 2, name: 'jim', title: 'nobody' },
{ id: 3, name: 'bob', title: 'dancer' }
];
var arr2 = [
{ id: 1, wage: '300', rate: 'day' },
{ id: 2, wage: '10', rate: 'hour' },
{ id: 4, wage: '500', rate: 'week' }
];
function combineArrays(arr1, arr2, keyFunc) {
var combined = [],
keys1 = arr1.map(keyFunc),
keys2 = arr2.map(keyFunc),
pos1 = keys1.map(function (id) {
return keys2.indexOf(id);
}),
pos2 = keys2.map(function (id) {
return keys1.indexOf(id);
});
arr1.forEach(function (item, i) {
combined.push( $.extend(item, arr2[pos1[i]]) );
});
arr2.forEach(function (item, i) {
if (pos2[i] === -1) combined.push( item );
});
return combined;
}
var combine = combineArrays(arr1, arr2, function (item) {
return item.id;
});
output(combine);
//
//
//
/* pretty Print */
function output(inp) {
var str = JSON.stringify(inp, undefined, 4);
$('body').append($('<pre/>').html(str));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

Manipulating objects in array of objects

I have this javascript objects:
var arr1 = [{id:'124',name:'qqq'},
{id:'589',name:'www'},
{id:'45',name:'eee'},
{id:'567',name:'rrr'}]
var arr2 = [{id:'124',name:'ttt'},
{id:'45',name:'yyy'}
I need to replace objects in arr1 with items from arr2 with same id.
Here how I achive the desired result:
arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
And here is the result:
var arr1 = [{id:'124',name:'ttt'},
{id:'589',name:'em'},
{id:'45',name:'yyy'},
{id:'567',name:'eme'}];
But the problem that this solution:
arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
Don't work in IE browser.
How can I change the row above to get the desired result in IE and chrome browsers?
var arr1 = [{
id: '124',
name: 'qqq'
}, {
id: '589',
name: 'www'
}, {
id: '45',
name: 'eee'
}, {
id: '567',
name: 'rrr'
}];
var arr2 = [{
id: '124',
name: 'ttt'
}, {
id: '45',
name: 'yyy'
}];
var res = arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
console.log(res);
If you want to use Array.prototype.find() you would need to use recommended polyfill for browsers that don't support it.
See MDN Array.protoype.find() polyfill
If you don't want to use a polyfill, simply reduce the ids first then map.
var arr1 = [{id:'124',name:'qqq'},
{id:'589',name:'www'},
{id:'45',name:'eee'},
{id:'567',name:'rrr'}]
var arr2 = [{id:'124',name:'ttt'},
{id:'45',name:'yyy'}]
var byIds = arr2.reduce((acc, item) => {
acc[item.id] = item;
return acc;
}, {})
var replacedArr1 = arr1.map(item => byIds[item.id] || item);
You have tagged lodash to this, so why not use lodash functions _ .find and _ .map instead of the native functions with limited browser support.
_.map(arr1, obj => _.find(arr2, o => o.id === obj.id) || obj);
To state the obvious, you also need to transpile the ES6 style arrow functions and what not to support older browsers.
Please, did you think of underscorejs you will find cross browser functions like find, filter and map
int lastIndex = 0
var result = _.map(arr1 , function(num){
if (arr1.id == arr2[lastIndex].id){
return arr2[lastIndex++];
}
return arr1;
});
You could iterate over arr2 and build an object as hash table and then iterate over arr1 for changing the elements.
var arr1 = [{ id: '124', name: 'qqq' }, { id: '589', name: 'www' }, { id: '45', name: 'eee' }, { id: '567', name: 'rrr' }],
arr2 = [{ id: '124', name: 'ttt' }, { id: '45', name: 'yyy' }],
hash = Object.create(null);
arr2.forEach(function (a) {
this[a.id] = a;
}, hash);
arr1.forEach(function (a, i, aa) {
if (this[a.id]) {
aa[i] = this[a.id];
}
}, hash);
console.log(arr1);
Or use a version with short circuit.
var arr1 = [{ id: '124', name: 'qqq' }, { id: '589', name: 'www' }, { id: '45', name: 'eee' }, { id: '567', name: 'rrr' }],
arr2 = [{ id: '124', name: 'ttt' }, { id: '45', name: 'yyy' }],
hash = Object.create(null);
hash.count = arr2.length;
arr2.forEach(function (a) {
this[a.id] = a;
}, hash);
arr1.some(function (a, i, aa) {
if (this[a.id]) {
aa[i] = this[a.id];
return !--this.count;
}
}, hash);
console.log(arr1);
What I would do is use a for loop to loop through each item in the 2nd array. Then loop through the first array to see if the ID matches. If it does, set the name to the name from the second array.
var arr1 = [{id:'124',name:'qqq'},
{id:'589',name:'www'},
{id:'45',name:'eee'},
{id:'567',name:'rrr'}];
var arr2 = [{id:'124',name:'ttt'},
{id:'45',name:'yyy'}];
for (var i = 0; i < arr2.length; i++) {
for (var j = 0; j < arr1.length; j++) {
if (arr2[i].id === arr1[j].id) {
arr1[j].name = arr2[i].name;
}
}
}
here is a fiddle https://jsfiddle.net/k0grurx5/

using javascript filter() with a flag

I want to return arr2 but want to prompt the user whether there's changes or not by comparing it with arr. with below's approach, I got id of undefined if arr2 have any missing item.
var arr = [{
id: 1,
name: 'something'
}, {
id: 2,
name: 'something2'
}]
var arr2 = [{
id: 1,
name: 'something'
}]
var result = arr.filter(function(obj, i) {
return obj.id == arr2[i].id;
});
document.write(JSON.stringify(result))
The problem in your code is that arr[1] is undefined and you are trying to get id property of undefined. Now what you can do is, get id's in array then get index and check based on that in filter.
var arr = [{
id: 1,
name: 'something'
}, {
id: 2,
name: 'something2'
}]
var arr2 = [{
id: 1,
name: 'something'
}];
var arrIds = arr2.map(function(v) {
return v.id;
});
var result = arr.filter(function(obj) {
var i = arrIds.indexOf(obj.id);
return i > -1 &&
obj.name == arr2[i].name; // check name property here
});
document.write(JSON.stringify(result))
Loop through arr2 in a callback of the .filter to test each item of arr2.
var arr = [{
id: 1,
name: 'something'
}, {
id: 2,
name: 'something2'
}]
var arr2 = [{
id: 1,
name: 'something'
}, {
id: 5,
name: 'something'
}, {
id: 8,
name: 'something'
}];
var isValInArr = function(arr, key, val) {
for (var i = 0, len = arr.length; i < len; i++) {
if (arr[i][key] === val) {
return true;
}
}
return false;
};
var result = arr.filter(function(obj, i) {
return isValInArr(arr2, 'id', obj.id);
});
document.write(JSON.stringify(result))

Categories

Resources