Related
I've tried modifying some of the similar solutions on here but I keep getting stuck, I believe I have part of this figured out however, the main caveat is that:
Some of the objects have extra keys, which renders my object comparison logic useless.
I am trying to compare two arrays of objects. One array is the original array, and the other array contains the items I want deleted from the original array. However there's one extra issue in that the second array contains extra keys, so my comparison logic doesn't work.
An example would make this easier, let's say I have the following two arrays:
const originalArray = [{id: 1, name: "darnell"}, {id: 2, name: "funboi"},
{id: 3, name: "jackson5"}, {id: 4, name: "zelensky"}];
const itemsToBeRemoved = [{id: 2, name: "funboi", extraProperty: "something"},
{id: 4, name: "zelensky", extraProperty: "somethingelse"}];
after running the logic, my final output should be this array:
[{id: 1, name: "darnell"}, {id: 3, name: "jackson5"}]
And here's the current code / logic that I have, which compares but doesn't handle the extra keys. How should I handle this? Thank you in advance.
const prepareArray = (arr) => {
return arr.map((el) => {
if (typeof el === "object" && el !== null) {
return JSON.stringify(el);
} else {
return el;
}
});
};
const convertJSON = (arr) => {
return arr.map((el) => {
return JSON.parse(el);
});
};
const compareArrays = (arr1, arr2) => {
const currentArray = [...prepareArray(arr1)];
const deletedItems = [...prepareArray(arr2)];
const compared = currentArray.filter((el) => deletedItems.indexOf(el) === -1);
return convertJSON(compared);
};
How about using filter and some? You can extend the filter condition on select properties using &&.
const originalArray = [
{ id: 1, name: 'darnell' },
{ id: 2, name: 'funboi' },
{ id: 3, name: 'jackson5' },
{ id: 4, name: 'zelensky' },
];
const itemsToBeRemoved = [
{ id: 2, name: 'funboi', extraProperty: 'something' },
{ id: 4, name: 'zelensky', extraProperty: 'somethingelse' },
];
console.log(
originalArray.filter(item => !itemsToBeRemoved.some(itemToBeRemoved => itemToBeRemoved.id === item.id))
)
Or you can generalise it as well.
const originalArray = [
{ id: 1, name: 'darnell' },
{ id: 2, name: 'funboi' },
{ id: 3, name: 'jackson5' },
{ id: 4, name: 'zelensky' },
];
const itemsToBeRemoved = [
{ id: 2, name: 'funboi', extraProperty: 'something' },
{ id: 4, name: 'zelensky', extraProperty: 'somethingelse' },
];
function filterIfSubset(originalArray, itemsToBeRemoved) {
const filteredArray = [];
for (let i = 0; i < originalArray.length; i++) {
let isSubset = false;
for (let j = 0; j < itemsToBeRemoved.length; j++) {
// check if whole object is a subset of the object in itemsToBeRemoved
if (Object.keys(originalArray[i]).every(key => originalArray[i][key] === itemsToBeRemoved[j][key])) {
isSubset = true;
}
}
if (!isSubset) {
filteredArray.push(originalArray[i]);
}
}
return filteredArray;
}
console.log(filterIfSubset(originalArray, itemsToBeRemoved));
Another simpler variation of the second approach:
const originalArray = [
{ id: 1, name: 'darnell' },
{ id: 2, name: 'funboi' },
{ id: 3, name: 'jackson5' },
{ id: 4, name: 'zelensky' },
];
const itemsToBeRemoved = [
{ id: 2, name: 'funboi', extraProperty: 'something' },
{ id: 4, name: 'zelensky', extraProperty: 'somethingelse' },
];
const removeSubsetObjectsIfExists = (originalArray, itemsToBeRemoved) => {
return originalArray.filter(item => {
const isSubset = itemsToBeRemoved.some(itemToBeRemoved => {
return Object.keys(item).every(key => {
return item[key] === itemToBeRemoved[key];
});
});
return !isSubset;
});
}
console.log(removeSubsetObjectsIfExists(originalArray, itemsToBeRemoved));
The example below is a reusable function, the third parameter is the key to which you compare values from both arrays.
Details are commented in example
const arr=[{id:1,name:"darnell"},{id:2,name:"funboi"},{id:3,name:"jackson5"},{id:4,name:"zelensky"}],del=[{id:2,name:"funboi",extraProperty:"something"},{id:4,name:"zelensky",extraProperty:"somethingelse"}];
/** Compare arrayA vs. delArray by a given key's value.
--- ex. key = 'id'
**/
function deleteByKey(arrayA, delArray, key) {
/* Get an array of only the values of the given key from delArray
--- ex. delList = [1, 2, 3, 4]
*/
const delList = delArray.map(obj => obj[key]);
/* On every object of arrayA compare delList values vs
current object's key's value
--- ex. current obj[id] = 2
--- [1, 2, 3, 4].includes(obj[id])
Any match returns an empty array and non-matches are returned
in it's own array.
--- ex. ? [] : [obj]
The final return is a flattened array of the non-matching objects
*/
return arrayA.flatMap(obj => delList.includes(obj[key]) ? [] : [obj]);
};
console.log(deleteByKey(arr, del, 'id'));
let ff = [{ id: 1, name: 'darnell' }, { id: 2, name: 'funboi' },
{ id: 3, name: 'jackson5' },
{ id: 4, name: 'zelensky' }]
let cc = [{ id: 2, name: 'funboi', extraProperty: 'something' },
{ id: 4, name: 'zelensky', extraProperty: 'somethingelse' }]
let ar = []
let out = []
const result = ff.filter(function(i){
ar.push(i.id)
cc.forEach(function(k){
out.push(k.id)
})
if(!out.includes(i.id)){
// console.log(i.id, i)
return i
}
})
console.log(result)
I have javascript array object as below. My need is to sum value base on seach id in the array object.
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
],
For example sum of value for id 1 is 10 + 30 + 25 + 20 = 85 , It may be something link linq but I'm not sure in javascript. Thanks for all answers.
You can use a combination of filter and reduce to get the result you want:
sumOfId = (id) => array.filter(i => i.id === id).reduce((a, b) => a + b.val, 0);
Usage:
const sumOf1 = sumOfId(1); //85
Reading material:
Array.prototype.filter
Array.prototype.reduce
A way to do it with a traditional for loop
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
];
var sums = {};
for (var i = 0; i < array.length; i++) {
var obj = array[i];
sums[obj.id] = sums[obj.id] === undefined ? 0 : sums[obj.id];
sums[obj.id] += parseInt(obj.val);
}
console.log(sums);
running example
You can use reduce() and findIndex()
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
];
let res = array.reduce((ac,a) => {
let ind = ac.findIndex(x => x.id === a.id);
ind === -1 ? ac.push(a) : ac[ind].val += a.val;
return ac;
},[])
console.log(res);
JS noob here ... I guess something like this should be here too :-)
let newArray = {}
array.forEach((e) => {
!newArray[e.id] && (newArray[e.id] = 0);
newArray[e.id] += e.val;
});
You can loop on the array and check the ids.
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
];
var sum = 0;
var id = 1;
$.each(array, function(index, object){
if (object.id == id) {
sum += object.val;
}
});
console.log(sum);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Using Array#reduce and Map you can get the sum for each id like so. This also uses destructuring to have quicker access to properties.
const data=[{id:1,val:10},{id:2,val:25},{id:3,val:20},{id:1,val:30},{id:1,val:25},{id:2,val:10},{id:1,val:20}];
const res = data.reduce((a,{id,val})=>{
return a.set(id, (a.get(id)||0) + val);
}, new Map())
console.log(res.get(1));
console.log(res.get(2));
If you wanted to output all the sums, then you need to use Array#from
const data=[{id:1,val:10},{id:2,val:25},{id:3,val:20},{id:1,val:30},{id:1,val:25},{id:2,val:10},{id:1,val:20}];
const res = Array.from(
data.reduce((a,{id,val})=>{
return a.set(id, (a.get(id)||0) + val);
}, new Map())
);
console.log(res);
If the format should be similar as to your original structure, you need to add a Array#map afterwards to transform it.
const data=[{id:1,val:10},{id:2,val:25},{id:3,val:20},{id:1,val:30},{id:1,val:25},{id:2,val:10},{id:1,val:20}];
const res = Array.from(
data.reduce((a,{id,val})=>{
return a.set(id, (a.get(id)||0) + val);
}, new Map())
).map(([id,sum])=>({id,sum}));
console.log(res);
You could take GroupBy from linq.js with a summing function.
var array = [{ id: 1, val: 10 }, { id: 2, val: 25 }, { id: 3, val: 20 }, { id: 1, val: 30 }, { id: 1, val: 25 }, { id: 2, val: 10 }, { id: 1, val: 20 }],
result = Enumerable
.From(array)
.GroupBy(null, null, "{ id: $.id, sum: $$.Sum('$.val') }", "$.id")
.ToArray();
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.js"></script>
Here is another option, introducing an Array.prototype.sum helper:
Array.prototype.sum = function (init = 0, fn = obj => obj) {
if (typeof init === 'function') {
fn = init;
init = 0;
}
return this.reduce(
(acc, ...fnArgs) => acc + fn(...fnArgs),
init
);
};
// .sum usage examples
console.log(
// sum simple values
[1, 2, 3].sum(),
// sum simple values with initial value
[1, 2, 3].sum(10),
// sum objects
[{ a: 1 }, { a: 2 }, { a: 3 }].sum(obj => obj.a),
// sum objects with initial value
[{ a: 1 }, { a: 2 }, { a: 3 }].sum(10, obj => obj.a),
// sum custom combinations
[{ amount: 1, price: 2 }, { amount: 3, price: 4 }]
.sum(product => product.amount * product.price)
);
var array = [{ id: 1, val: 10 }, { id: 2, val: 25 }, { id: 3, val: 20 }, { id: 1, val: 30 }, { id: 1, val: 25 }, { id: 2, val: 10 }, { id: 1, val: 20 }];
// solutions
console.log(
array.filter(obj => obj.id === 1).sum(obj => obj.val),
array.filter(({id}) => id === 1).sum(({val}) => val),
array.sum(({id, val}) => id === 1 ? val : 0)
);
references:
Array.prototype.reduce
Array.prototype.filter
Arrow functions used in sum(obj => obj.val)
Object destructing assignment used in ({id}) => id === 1
Rest parameters used in (acc, ...fnArgs) => acc + fn(...fnArgs)
Conditional (ternary) operator used in id === 1 ? val : 0
I just learned a new trick to find the same object in 2 array object, it works very well. it uses array.filter and array.some, as code bellow, but I don't understand how filter() can run when some() will return true or false.
const similarity = (arr, values) => arr.filter(item => values.some(m => (m.id === item.id) && (m.name === item.name)));
my input:
let arr1 = [
{
id: 1,
name: "kiet"
},
{
id: 2,
name: 'phan'
},
{
id: 3,
name: 'tuan'
}]
let arr2 = [
{
id: 1,
name: "kiet"
},
{
id: 2,
name: 'haha'
},
{
id: 5,
name: 'tuan'
}
]
my result :
[ { id: 1, name: 'kiet' } ]
You are Filtering the array, then passing this condition inside the some
(m.id === item.id) && (m.name === item.name)
If the id of the second array (here, m is the second array's objects) is equal to the first array's id (here, item is the array's objects) and the name is equal to the first array's name property. If yes then it will return true. So the filter gets a true and if is does, it will return that particular object for which it gets a true
let arr1 = [{ id: 1, name: "kiet" }, { id: 2, name: 'phan' }, { id: 3, name: 'tuan'}]
let arr2 = [ { id: 1, name: "kiet" }, { id: 2, name: 'haha' }, { id: 5, name: 'tuan' } ]
const similarity = (arr, values) => arr.filter(item => values.some(m => (m.id === item.id) && (m.name === item.name)));
console.log(similarity(arr1,arr2))
You get the elements from the array which have the same properties id/name as the values array.
Array#filter needs a (kind of) boolean value and if true or truthy, then the item is taken to the new array.
Array#some checks an item and if the callback returns a truthy value, then it returns true, if not then false.
const
similarity = (array, values) => array.filter(item => values.some(m => m.id === item.id && m.name === item.name)),
arr1 = [ { id: 1, name: "kiet" }, { id: 2, name: 'phan' }, { id: 3, name: 'tuan' }],
arr2 = [ { id: 1, name: "kiet" }, { id: 2, name: 'haha' }, { id: 5, name: 'tuan' }],
result = similarity(arr1, arr2);
console.log(result);
For larger data sets, you could take a Set, this is iterated once with a combined value and checked against for filtering.
const
similarity = (array, values) => {
const
getKey = ({ id, name }) => [id, name].join('|'),
keys = new Set(values.map(getKey));
return array.filter(o => keys.has(getKey(o)));
},
arr1 = [ { id: 1, name: "kiet" }, { id: 2, name: 'phan' }, { id: 3, name: 'tuan' }],
arr2 = [ { id: 1, name: "kiet" }, { id: 2, name: 'haha' }, { id: 5, name: 'tuan' }],
result = similarity(arr1, arr2);
console.log(result);
This is a good technique if you want to check for array intersection.
const vowels = [...'AEIOU'];
const isVowel = x => vowels.some(v => v === x);
const hasVowel = string => [...string].filter(isVowel).length > 0;
I have javascript array object as below. My need is to sum value base on seach id in the array object.
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
],
For example sum of value for id 1 is 10 + 30 + 25 + 20 = 85 , It may be something link linq but I'm not sure in javascript. Thanks for all answers.
You can use a combination of filter and reduce to get the result you want:
sumOfId = (id) => array.filter(i => i.id === id).reduce((a, b) => a + b.val, 0);
Usage:
const sumOf1 = sumOfId(1); //85
Reading material:
Array.prototype.filter
Array.prototype.reduce
A way to do it with a traditional for loop
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
];
var sums = {};
for (var i = 0; i < array.length; i++) {
var obj = array[i];
sums[obj.id] = sums[obj.id] === undefined ? 0 : sums[obj.id];
sums[obj.id] += parseInt(obj.val);
}
console.log(sums);
running example
You can use reduce() and findIndex()
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
];
let res = array.reduce((ac,a) => {
let ind = ac.findIndex(x => x.id === a.id);
ind === -1 ? ac.push(a) : ac[ind].val += a.val;
return ac;
},[])
console.log(res);
JS noob here ... I guess something like this should be here too :-)
let newArray = {}
array.forEach((e) => {
!newArray[e.id] && (newArray[e.id] = 0);
newArray[e.id] += e.val;
});
You can loop on the array and check the ids.
var array = [
{ id: 1, val: 10 },
{ id: 2, val: 25 },
{ id: 3, val: 20 },
{ id: 1, val: 30 },
{ id: 1, val: 25 },
{ id: 2, val: 10 },
{ id: 1, val: 20 }
];
var sum = 0;
var id = 1;
$.each(array, function(index, object){
if (object.id == id) {
sum += object.val;
}
});
console.log(sum);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Using Array#reduce and Map you can get the sum for each id like so. This also uses destructuring to have quicker access to properties.
const data=[{id:1,val:10},{id:2,val:25},{id:3,val:20},{id:1,val:30},{id:1,val:25},{id:2,val:10},{id:1,val:20}];
const res = data.reduce((a,{id,val})=>{
return a.set(id, (a.get(id)||0) + val);
}, new Map())
console.log(res.get(1));
console.log(res.get(2));
If you wanted to output all the sums, then you need to use Array#from
const data=[{id:1,val:10},{id:2,val:25},{id:3,val:20},{id:1,val:30},{id:1,val:25},{id:2,val:10},{id:1,val:20}];
const res = Array.from(
data.reduce((a,{id,val})=>{
return a.set(id, (a.get(id)||0) + val);
}, new Map())
);
console.log(res);
If the format should be similar as to your original structure, you need to add a Array#map afterwards to transform it.
const data=[{id:1,val:10},{id:2,val:25},{id:3,val:20},{id:1,val:30},{id:1,val:25},{id:2,val:10},{id:1,val:20}];
const res = Array.from(
data.reduce((a,{id,val})=>{
return a.set(id, (a.get(id)||0) + val);
}, new Map())
).map(([id,sum])=>({id,sum}));
console.log(res);
You could take GroupBy from linq.js with a summing function.
var array = [{ id: 1, val: 10 }, { id: 2, val: 25 }, { id: 3, val: 20 }, { id: 1, val: 30 }, { id: 1, val: 25 }, { id: 2, val: 10 }, { id: 1, val: 20 }],
result = Enumerable
.From(array)
.GroupBy(null, null, "{ id: $.id, sum: $$.Sum('$.val') }", "$.id")
.ToArray();
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.js"></script>
Here is another option, introducing an Array.prototype.sum helper:
Array.prototype.sum = function (init = 0, fn = obj => obj) {
if (typeof init === 'function') {
fn = init;
init = 0;
}
return this.reduce(
(acc, ...fnArgs) => acc + fn(...fnArgs),
init
);
};
// .sum usage examples
console.log(
// sum simple values
[1, 2, 3].sum(),
// sum simple values with initial value
[1, 2, 3].sum(10),
// sum objects
[{ a: 1 }, { a: 2 }, { a: 3 }].sum(obj => obj.a),
// sum objects with initial value
[{ a: 1 }, { a: 2 }, { a: 3 }].sum(10, obj => obj.a),
// sum custom combinations
[{ amount: 1, price: 2 }, { amount: 3, price: 4 }]
.sum(product => product.amount * product.price)
);
var array = [{ id: 1, val: 10 }, { id: 2, val: 25 }, { id: 3, val: 20 }, { id: 1, val: 30 }, { id: 1, val: 25 }, { id: 2, val: 10 }, { id: 1, val: 20 }];
// solutions
console.log(
array.filter(obj => obj.id === 1).sum(obj => obj.val),
array.filter(({id}) => id === 1).sum(({val}) => val),
array.sum(({id, val}) => id === 1 ? val : 0)
);
references:
Array.prototype.reduce
Array.prototype.filter
Arrow functions used in sum(obj => obj.val)
Object destructing assignment used in ({id}) => id === 1
Rest parameters used in (acc, ...fnArgs) => acc + fn(...fnArgs)
Conditional (ternary) operator used in id === 1 ? val : 0
I have an array object:
[
{ id:1, name: 'Pedro'},
{ id:2, name: 'Miko'},
{ id:3, name: 'Bear'},
{ id:4, name: 'Teddy'},
{ id:5, name: 'Mouse'}
]
And I have an array with ids [1, 3, 5],
How can I filter the array object to leave records only with id's from the second one?
If Array.includes() is supported, you can use it with Array.filter() to get the items:
const array = [
{ id: 1, name: 'Pedro'},
{ id: 2, name: 'Miko'},
{ id: 3, name: 'Bear'},
{ id: 4, name: 'Teddy'},
{ id: 5, name: 'Mouse'}
];
const filterArray = [1,3,5];
const result = array.filter(({ id }) => filterArray.includes(id));
console.log(result);
If includes is not supported, you can use Array.indexOf() instead:
var array = [
{ id: 1, name: 'Pedro'},
{ id: 2, name: 'Miko'},
{ id: 3, name: 'Bear'},
{ id: 4, name: 'Teddy'},
{ id: 5, name: 'Mouse'}
];
var filterArray = [1,3,5];
var result = array.filter(function(item) {
return filterArray.indexOf(item.id) !== -1;
});
console.log(result);
Maybe take a Array.prototype.reduce in combination with an Array.prototype.some. This keeps the order of the given array need.
var data = [
{ id: 3, name: 'Bear' },
{ id: 4, name: 'Teddy' },
{ id: 5, name: 'Mouse' },
{ id: 1, name: 'Pedro' },
{ id: 2, name: 'Miko' },
],
need = [1, 3, 5],
filtered = need.reduce(function (r, a) {
data.some(function (el) {
return a === el.id && r.push(el);
});
return r;
}, []);
document.write('<pre>' + JSON.stringify(filtered, 0, 4) + '</pre>');
To keep the order of data you can use Array.prototype.filter:
var data = [
{ id: 3, name: 'Bear' },
{ id: 4, name: 'Teddy' },
{ id: 5, name: 'Mouse' },
{ id: 1, name: 'Pedro' },
{ id: 2, name: 'Miko' },
],
need = [1, 3, 5],
filtered = data.filter(function (a) {
return ~need.indexOf(a.id);
});
document.write('<pre>' + JSON.stringify(filtered, 0, 4) + '</pre>');
In case the data set is small, you are ok with any of the offered solution (ones that use indexOf).
However, these solutions are O(n^2) ones, therefore, given the data set big enough, the lag can become noticeable. In this case, you should build an index prior to selecting elements.
Example:
function filterFast(data, ids) {
var index = ids.reduce(function(a,b) {a[b] = 1; return a;}, {});
return data.filter(function(item) {
return index[item.id] === 1;
});
}
And some benchmarking can be tested here.
You can use the filter method on your Array:
var data = [
{ id:1, name: 'Pedro'},
{ id:2, name: 'Miko'},
{ id:3, name: 'Bear'},
{ id:4, name: 'Teddy'},
{ id:5, name: 'Mouse'}
];
var ids = [1, 3, 5];
var filteredData = filterData(data, 'id', ids[1]);
function filterData(data, prop, values) {
return data.filter(function(item) {
return ~values.indexOf(item[prop]); // ~ returns 0 if indexOf returns -1
});
}
See it in action in this JSFiddle.
Or if you are using jQuery, another option may be:
var arr1 = [1, 3, 5],
arr2 = [{ id: 1, name: 'Pedro' },
{ id: 2, name: 'Miko' },
{ id: 3, name: 'Bear' },
{ id: 4, name: 'Teddy' },
{ id: 5, name: 'Mouse' }],
filtered = $.grep(arr2, function (item) {
if (arr1.indexOf(item.id) > -1) {
return true;
}
});
You can use a for loop on the object array and check hasOwnProperty in another for loop for each ids in [1,3,5] (break out of the loop once an id found). (And break out of the bigger for-loop once all ids are found) If your array object is ordered (e.g. elements sorted from smallest id to biggest id) and so are your list, this solution should be quite efficient.
var c = 0;
for(var i =0; i< objects.length; i++){
for(var v =0; v< list.length; v++)
if(objects[i].hasOwnProperty(list[v])){
delete objects[i]; c++; break;
}
if(c===list.length) break;
}
or use array.splice( i, 1 ); if you don't want an empty slot.
Using filter and indexOf will do the trick:
var filteredArray = dataArray.filter(function(obj) {
return idsArray.indexOf(obj.id) > -1;
});
However, indexOf has linear performance, and it will be called lots of times.
In ES6 you can use a set instead, whose has call has sublinear performance (on average):
var idsSet = new Set(idsArray),
filteredArray = dataArray.filter(obj => idsSet.has(obj.id));
Assuming the toString method of your ids is injective, you can achieve something similar in ES5:
var idsHash = Object.create(null);
idsArray.forEach(function(id) {
idsHash[id] = true;
});
var filteredArray = dataArray.filter(function(obj) {
return idsHash[obj.id];
});