Extract from an array of objects ones that have propertie using lodash - javascript

I have a big array of objects and i need to get the objects that have the propertie def set. No mather the value...
Thanks in advance.

You can use hasOwnProperty to check if a property is present, and Array.prototype.filter to filter only those items.
objArray = [ { def: 1, bar: 2}, { foo: 3, bar: 4}, { def: 5, bar: 6} ];
var result = objArray.filter(item => item.hasOwnProperty('def'));
console.log(result);
for es5 compatibility
objArray = [{
def: 1,
bar: 2
}, {
foo: 3,
bar: 4
}, {
def: 5,
bar: 6
}];
var result = objArray.filter(function(item) {
return item.hasOwnProperty('def')
});
console.log(result);

There is not such function in lodash although you can try following code
`let aFilteredArray = [];
_.forEach(YourArray,function(oElement){
if(!_.isEmpty(oElement.def)){
aFilteredArray.push(oElement);
}
};

Related

Convert array of objects into subarrays of objects by a selected property (javascript)

I am looking to take an array of objects, and convert it into an array of subarrays based on a chosen object property
for example:
[
{foo: 1, bar: a}, {foo: 2, bar: b}, {foo: 1, bar: c}, {foo: 2, bar: d}
]
Create subarrays with the foo property would become:
[
[
{foo: 1, bar: a}, {foo: 1, bar: c},
],
[
{foo: 2, bar: b}, {foo: 2, bar: d}
]
]
I can't think of an efficient way to this. I keep resorting to creating a set of all of the unique property values of my chosen value, and then brute forcing through it multiple times.
const distinctProperties = [...new Set(originalArray.map(item => item.foo))]
const newArray = distinctProperties.map(item => originalArray.filter(obj => obj.foo === item))
Thanks in advance for some advice here!
can be done with reduce. you can wrap this around another function to group by the key you want.
Here I'm grouping based on the value of foo and res will be like this
{
1: [{
bar: "a",
foo: 1
}, {
bar: "c",
foo: 1
}],
2: [{
bar: "b",
foo: 2
}, {
bar: "d",
foo: 2
}]
}
then I'm taking Object.values of this to get the array format you want
let a =[
{foo: 1, bar: 'a'}, {foo: 2, bar: 'b'}, {foo: 1, bar: 'c'}, {foo: 2, bar: 'd'}
]
let res= Object.values(a.reduce((acc,curr)=> {
if(!acc[curr.foo])acc[curr.foo]=[];
acc[curr.foo].push(curr)
return acc;
},{}))
console.log(res)
As a generalized function to take key name as input
let a =[
{foo: 1, bar: 'a'}, {foo: 2, bar: 'b'}, {foo: 1, bar: 'c'}, {foo: 2, bar: 'd'}
]
let groupByValue = (arr,key) => {
return Object.values(arr.reduce((acc,curr)=> {
if(!acc[curr[key]])acc[curr[key]]=[];
acc[curr[key]].push(curr)
return acc;
},{}))
}
let res1 = groupByValue(a,'foo')
let res2 = groupByValue(a,'bar')
console.log(res1)
console.log(res2)

How to filter an Array with another Array

I have an Array of Objects:
const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }]
I have a second array containing the ID's that I want to filter out of the first Array:
const ids = [1, 2]
How do I create a new Array of Objects without the ID's found in ids.
This is a fairly simple filter operation
const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1, 2];
var result = array.filter( x => !ids.includes(x.id));
console.log(result);
If you need to mutate the original array you can do like this:
const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1, 2];
ids.forEach(idToDelete => {
const index = array.findIndex(({ id }) => id === idToDelete);
array.splice(index, 1);
});
console.log(array);
If you need a new array you can do like this:
const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1, 2];
const result = array.filter(({ id }) => !ids.includes(id));
console.log(result);
You could also reassign a new array to the array variable:
let array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1, 2];
array = array.filter(({ id }) => !ids.includes(id));
console.log(array);
Use Array.filter :
let array = [
{id: 1, bar: "test" },
{id: 2, bar: "test2" },
{id: 3, bar: "test3" }
];
let ids = [1,2];
let filteredArray = array.filter(row=>!ids.includes(row.id));
console.log(filteredArray);
Use this oneliner from lodash.
const _ = require("lodash");
let filteredArray = _.remove(array, el=>[1,2].includes(el.id))
Use filter and indexOf.
const arr = [{ id: 1, bar: 'test' }, { id: 2, bar: 'test2' }, { id: 3, bar: 'test3' }];
const ids = [1, 2];
const result = arr.filter(element => ids.indexOf(element.id) === -1);
console.log(result);
We can filter an array in JavaScript using Array filter()
const myArray = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }]
const ids = [1,2]
const resultArray = myArray.filter(item => !ids.includes(item.id));
console.log(resultArray);
In term of performance the best solution will be the next one:
let array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
const ids = [1,2];
const idSet = new Set();
for (const id of ids) {
idSet.add(id);
}
array = array.filter(x => !set.has(x.id));
//const newArray if you need the initial array unmodified
In this case we perform two consequencial iteration instead of a nested one, so the time complexity will be O(n) instead of O(n^2);
##Edit
If you instead need the initial array to be mutated and not overwritten you can use this approach:
const ids = [1,2];
const array = [{id: 1, bar: "test" }, {id: 2, bar: "test2" }, {id: 3, bar: "test3" }];
for (const id of ids) {
const index = array.findIndex(x => x.id == id);
array.splice(index, 1);
}
In the second case the time complexity will be O(n*m), where n is array length and m is ids length.
I want to propose something wildly different.
In my case, I wanted to filter one list of unique IDs against another.
I was curious if regex could do it faster.
Such a method really only works with one-dimensional arrays of simple objects.
It's probably best if items a single regex 'word' (string of 0-9a-z_).
A list of ids works perfect.
array.filter works best on small datasets (1,000), usually slightly faster
regex worked 66% faster on large datasets (10,000)
regex speed advantage widens. 90% faster on 100,000.
On comparing two arrays of 1m items, filter didn't do anything for me after more than 90 seconds. Regex returned a result in six seconds.
In this case, the input is number[], and the output is string[], which works for my purposes, but you can use map to convert back to numbers if you need, .
var listlength = 10000;
function createArray() {
let arr = new Set();
for (let i = 0; i < listlength; i++) {
arr.add(Math.floor(Math.random() * listlength));
}
return arr;
}
function filter() {
let arr1 = Array.from(createArray());
let arr2 = Array.from(createArray());
let start = +new Date();
let arr3 = arr1.filter((n) => !arr2.includes(n));
console.log('filter', (+new Date() - start) + 'ms', arr1.length, arr2.length, arr3.length);
}
function regex() {
let arr1 = Array.from(createArray());
let arr2 = Array.from(createArray());
let start = +new Date();
let str1 = arr1.join(',') + ',';
str1 = str1.replace(new RegExp('\\b(' + arr2.join('|') + '),', 'g'), '');
let result = str1.split(',') // .map(e=>Number(e)); (to convert back to number[])
result.pop();
console.log('regex', (+new Date() - start) + 'ms', arr1.length, arr2.length, result.length);
}
for (let x = 0; x < 10; x++) {
console.log(`try ${x}`);
filter();
regex();
}
On my NodeJS app, sets of 100,000, regex more than 90% faster.

extracting object from array of array using es6

how can i return an array of objects taking from array of again one more level array. I am using push.
is there any better way to achieve this
let a = [{b: [{c: "k"}]}]
let o = []
a.forEach(so => {so.b.forEach(obc => o.push(obc))})
console.log(o)
I'd use flatMap() instead:
const a = [{
b: [{
foo: 'foo'
}]
},
{
b: [{
c: "k"
},
{
bar: 'bar'
}
]
}
];
const o = a.flatMap(({ b }) => b);
console.log(o);
(but this is a relatively new method, so if you want to use it and still support older environments, be sure to include a polyfill)
Lacking that, you can also improve your existing code by using concat() with the inner array instead of iterating over each inner item:
const a = [{
b: [{
foo: 'foo'
}]
},
{
b: [{
c: "k"
},
{
bar: 'bar'
}
]
}
];
let o = [];
a.forEach(({ b }) => {
o = o.concat(b);
});
console.log(o);
Try
let a = [{b: [{c: "k"}]}]
let o =a[0].b
console.log(o)

Array of objects to object of property values

I have this data:
[
{foo: 1, bar: a},
{foo: 2, bar: b},
{foo: 3, bar: c},
]
What's the simplest way to transform the data to something like
{
customLabel1 : [1,2,3],
customLabel2 : [a,b,c]
}
I come up with this
{
customLabel1: data.map((a) => {return a.foo} ),
customLabel2: data.map((a) => {return a.bar} )
}
Is there a simpler way to do this, or faster?
If you want simpler, your code is already pretty close with fat arrow syntax. You can drop the parentheses and the return keyword:
{
customLabel1: data.map(a => a.foo),
customLabel2: data.map(a => a.bar)
}
If you want faster, I think you'll have to sacrifice some simplicity. As it's written, you're looping over data twice. If you iterated once, it would look something like this:
var data = [
{foo: 1, bar: 'a'},
{foo: 2, bar: 'b'},
{foo: 3, bar: 'c'},
];
var o = {customLabel1: [], customLabel2: []};
data.forEach(a => {
o.customLabel1.push(a.foo);
o.customLabel2.push(a.bar);
});
console.log(o);
You can use this form if you dont know the keys
{
customLabel1: data.map(function(element) { return element[Object.keys(element)[0]];}),
customLabel2: data.map(function(element) { return element[Object.keys(element)[1]];})
}
You could use an object for the key mapping and iterate then.
var data = [{ foo: 1, bar: 'a' }, { foo: 2, bar: 'b' }, { foo: 3, bar: 'c' }],
labels = { customLabel1: 'foo', customLabel2: 'bar' },
result = {};
data.forEach(a => Object.keys(labels).forEach(k => {
result[k] = result[k] || [];
result[k].push(a[labels[k]]);
}));
console.log(result);
The shorter syntax of the map call can be:
data.map(el => el.prop);
Having said that, I'd define a helper function for this:
function pluck(arr, props) {
return Object.keys(props).reduce((ret, prop) => {
ret[prop] = arr.map(el => el[props[prop]]);
return ret;
}, {});
}
var ret = pluck(data, {
customLabel1: 'foo',
customLabel2: 'bar'
});

Can I get the benefits of both, objects and arrays in JavaScript?

I have parts of data tagged with IDs distributed in different collections.
I need to access this data directly with the ID, but I also need to loop over the data really fast.
var listOfPartA = {
34523: { foo: 7, bar: 123},
6435: { foo: 2, bar: 163},
3123: { foo: 3, bar: 223},
...
};
var listOfPartB = {
34523: { baz: 1},
6435: { baz: 4},
3123: { baz: 6},
...
};
If I need to get specific dataparts for an Id it's fast, but If I try to loop all the dataparts it's slow.
var listOfPartA = [
{ id: 34523, foo: 7, bar: 123},
{ id: 6435, foo: 2, bar: 163},
{ id: 3123, foo: 3, bar: 223},
...
];
var listOfPartB = [
{ id: 34523, baz: 1},
{ id: 6435, baz: 4},
{ id: 3123, baz: 6},
...
];
If I want to get specific dataparts for an ID of these objects it is slow, because I have to search for them manually, but If I loop over all dataparts it's fast.
Can't I have fast direct access and fast iteration?
Pre-index your array:
var listOfPartA = [
{id:34523, foo:7 bar:123},
...
];
var lookupPartA = {};
listOfPartA.forEach(function(x,i) {lookupPartA[x.id] = i;});
Now, you can loop quickly with the listOfPartA array, but also find quickly:
listOfPartA[lookupPartA[34523]]
Pre-index your object:
var lookupPartA = {
34523: { foo: 7, bar: 123},
...
};
var listOfIds = Object.keys(lookupPartA);
Now, you can find ids quickly in the lookupPartA object, but also loop quickly:
for (var i=0, l=listOfIds.length; i<l; i++)
lookupPartA[listOfIds[i]]
According to theses tests, arrays are always fasters than objects.
array vs object performance test
object vs array vs native linked list
benchmark comparison

Categories

Resources