Iterating and filtering with ES6/lodash - javascript

We have an array of objects like:
const persons = [{
name: "john",
age: 23
}, {
name: "lisa",
age: 43
}, {
name: "jim",
age: 101
}, {
name: "bob",
age: 67
}];
And an array of a attribute values of the objects in object
const names = ["lisa", "bob"]
How can we find persons with name in the names array using es6, like:
const filteredPersons = [{
name: "lisa",
age: 43
}, {
name: "bob",
age: 67
}];

ES6
Use filter function with predicate and in it check the existence of the name in the names array.
const persons = [
{name: "john", age:23},
{name: "lisa", age:43},
{name: "jim", age:101},
{name: "bob", age:67}
];
const names = ["lisa", "bob"];
const filtered = persons.filter(person => names.includes(person.name));
console.log(filtered);

You can use filter() and inlcudes() to get required result.
DEMO
const persons = [{
name: "john",
age: 23
}, {
name: "lisa",
age: 43
}, {
name: "jim",
age: 101
}, {
name: "bob",
age: 67
}];
const names = ["lisa", "bob"];
console.log(persons.filter(({
name
}) => names.includes(name)))
.as-console-wrapper { max-height: 100% !important; top: 0; }

I would suggest to use indexOf as includes does not work in IE browser. Also, using {name} works as Destructuring assignment that will hold the value of name property of the object.
const persons = [{
name: "john",
age: 23
}, {
name: "lisa",
age: 43
}, {
name: "jim",
age: 101
}, {
name: "bob",
age: 67
}];
const names = ["lisa", "bob"];
console.log(persons.filter(({name}) => names.indexOf(name) !== -1))

lodash
You can try following
const persons = [{name: "john", age: 23},
{name: "lisa",age: 43},
{name: "jim", age: 101},
{name: "bob",age: 67}];
const names = ["lisa", "bob"]
const filteredPersons = _.filter(persons, function(person) {
return _.indexOf(names, person.name) !== -1;
});
console.log(filteredPersons);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>

In case you want to perform it in n complexity, here is a way to do it:
Create a map with key as person's name and value as person's object.
Map the criteria array and extract the person objects from the map create in step 1.
Here is a working demo:
const persons = [{
name: "john",
age: 23
}, {
name: "lisa",
age: 43
}, {
name: "jim",
age: 101
}, {
name: "bob",
age: 67
}];
const names = ["lisa", "bob"];
const map = persons.reduce((acc, item) => {
acc[item.name] = item;
return acc;
}, {});
const result = names.map(name => map[name]);
console.log(result);
Note: This solution assumes that only unique person names are in the source array. It needs to be tweaked to handle duplicates.

See Closures, Set, and Array.prototype.filter() for more info.
// Input.
const persons = [{name: "john",age: 23}, {name: "lisa",age: 43}, {name: "jim",age: 101}, {name: "bob",age: 67}]
const names = ["lisa", "bob"]
// Filter.
const filter = (A, B) => (s => A.filter(x => s.has(x.name)))(new Set(B))
// Output.
const output = filter(persons, names)
// Proof.
console.log(output)

Related

How do I convert an array of objects into an object (dynamically) in JavaScript [duplicate]

This question already has answers here:
Convert array of objects with same property to one object with array values
(6 answers)
Closed 2 months ago.
I have an array of objects that looks like this:
arr = [
{name: "john", age: 23},
{name: "mary", age: 40},
{name: "zack", age: 17}
]
I am trying to convert it into something like this:
{
name: ["john", "mary", "zack"],
age: ['23', 40, 17]
}
i have tried the following
arr.map(item => item.name)
arr.map(item => item.age)
return {names, ages}
and it works fine but this assumes that you already know, beforehand, the keys of the objects you're converting.
I want to be able to load the object keys and corresponding array of values dynamically. Assuming i don't know that the objects in our example array have "name" and "age" as keys.
You could reduce the array and the entries of the object and collect the values in the group of the keys.
const
data = [{ name: "john", age: 23 }, { name: "mary", age: 40 }, { name: "zack", age: 17 }],
result = data.reduce((r, o) => Object.entries(o).reduce((t, [k, v]) => {
if (!t[k]) t[k] = [];
t[k].push(v);
return t;
}, r), {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could get the key of the first element and then map through it. With each, get its corresponded values
const arr = [
{ name: "john", age: 23, gender: "male" },
{ name: "mary", age: 40, gender: "female" },
{ name: "zack", age: 17, gender: "male" },
]
const res = Object.keys(arr[0]).reduce((acc, el) => {
const values = arr.map((item) => item[el])
return { ...acc, [el]: values }
}, {})
console.log(res)
Assuming that each object in your list has the same keys you could get the keys of the first object
const keys = Object.keys(arr[0])
and then map through the keys with your above approach
const returnObj = {}
keys.forEach(key => {
returnObj[key] = arr.map(item => item[key])
})
return returnObj
You can use Object.entries for the mapping.
var arr = [
{name: "john", age: 23},
{name: "mary", age: 40},
{name: "zack", age: 17}
];
var entries = arr.map((item) => Object.entries(item));
var result = {};
entries.forEach(entry => {
entry.forEach(item => {
if (result[item[0]] && result[item[0]].length > 0) {
result[item[0]].push(item[1]);
} else {
result[item[0]] = [item[1]];
}
});
});
console.log(result);
You can make use of Array.reduce and Object.keys.
let arr = [
{name: "john", age: 23},
{name: "mary", age: 40},
{name: "zack", age: 17}
]
const formatData = (data) => {
return data.reduce((res, obj) => {
Object.keys(obj).map(d => {
res[d] = [...(res[d] ||[]), obj[d]]
})
return res;
}, {})
}
console.log(formatData(arr))
You can do this with Ramda
import { mergeWith, concat } from “Ramda”
const mergeConcat = mergeWith(concat)
mergeConcat(arr)

compare an array and object to see if item exists

I have the following:
An array
const myArray = ['john', 'frank', 'paul'];
then I have an array of objects
const myObjectArray = [
{name: 'nery', age: 34, present: true},
{name: 'john', age: 15, present: false},
etc
]
How can I check if myArray value is found in the myObjectArray?
I thought about looping through myArray and then in each iteration looping through myObjectArray to see if it is present. However this seems so 2001.
Any ideas?
You can use the Array.prototype.some and Array.prototype.includes functions.
const names = ['john', 'frank', 'paul'];
const people = [
{name: 'nery', age: 34, present: true},
{name: 'john', age: 15, present: false},
];
const exists = people.some(({ name }) => names.includes(name));
console.log(exists);
Array.prototype.find can find the first element in the provided array that satisfies the provided testing function.
const myArray = ["john", "frank", "paul"];
const myObjectArray = [
{ name: "nery", age: 34, present: true },
{ name: "john", age: 15, present: false },
];
res = myObjectArray.find((o) => myArray.includes(o.name));
console.log(res);
if you want to check if an item from first array is in the name of second array use some to return a boolean
const myArray = ["john", "frank", "paul"];
const myObjectArray = [
{ name: "nery", age: 34, present: true },
{ name: "john", age: 15, present: false },
];
res = myObjectArray.some((o) => myArray.includes(o.name));
console.log(res);
If you want to return the object that has same name from first array use filter
const myArray = ["john", "frank", "paul"];
const myObjectArray = [
{ name: "nery", age: 34, present: true },
{ name: "john", age: 15, present: false },
];
res = myObjectArray.filter((o) => myArray.includes(o.name));
console.log(res);

Filtering object keys inside an array of objects

Let's assume I'm obtaining an array of objects from a Node Repository, for example:
results = [
{
name: "John",
surname: "Fool",
age: 22
},
{
name: "Erik",
surname: "Owl",
age: 38
}
]
How can I filter every object taking only the keys I need, for example avoiding 'age' key?
filteredResults = [
{
name: "John",
surname: "Fool",
},
{
name: "Erik",
surname: "Owl",
}
]
I've already obtained this by creating another empty array and populating it by looping on the original one, but in case of large-data this would be heavy.
repository.retrieve((error, result) => {
let filteredData = [];
result.forEach(r => {
filteredData.push({
name: r.name,
description: r.description,
});
});
});
In SQL, I would obtain it this way:
SELECT `name, description` FROM results;
You can just rebuild the object as you want
{
name: rec.name,
surname: rec.surname
}
const results = [
{
name: "John",
surname: "Fool",
age: 22
},
{
name: "Erik",
surname: "Owl",
age: 38
}
]
const result = results.map((rec) => {
return {
name: rec.name,
surname: rec.surname
}
})
console.log(result)
Or delete fields that is useless
const results = [
{
name: "John",
surname: "Fool",
age: 22
},
{
name: "Erik",
surname: "Owl",
age: 38
}
]
const result = results.map((rec) => {
delete rec.age
return rec
})
console.log(result)
I suggest you can tell more about what you will need to perform on the output to get the answer that can help.
Case 1. if your original list will survive and you accept your "modified list" to always follow the original list, you may use a generator to wrap your original object, by always not returning those extra properties.
Case 2. if you really want a query system, you may try using real DB thing such as levelDB
Case 3. if you need to display the modified list, write a simple wrapper to fit the format of each list item
Case 4. if you need to snapshot the modified list as object, the method you already made is already a very reasonable method
Case 5. if you need to snapshot the modified list as another output, you can try to directly obtain such output rather than making the intermediate object
You can use map and reduce to simplify this, which obviates the need to create a new array.
var results = [ { name: "John", surname: "Fool", age: 22 }, { name: "Erik", surname: "Owl", age: 38 } ];
let keys = ['name', 'surname'];
var filtered = results.map(obj=>
keys.reduce((acc,curr)=>(acc[curr]=obj[curr],acc), {}));
console.log(filtered);
You can also use object destructuring.
var results = [ { name: "John", surname: "Fool", age: 22 }, { name: "Erik", surname: "Owl", age: 38 } ];
var filtered = results.map(({name,surname})=>({name,surname}));
console.log(filtered);
Take a look at Array.map.It creates the transformed array.
let arr = [
{
name: "John",
surname: "Fool",
age: 22
},
{
name: "Erik",
surname: "Owl",
age: 38
}
]
let result = arr.map((elem) => {
return {
name: elem.name,
surname: elem.surname
}
});
console.log(result);
You can use Array.map() to transform individual elements of the array. And in the callback function use Object destructuring assignment to use only the keys you are interested in and return a new object with only those keys.
let results = [
{ name: "John", surname: "Fool", age: 22 },
{ name: "Erik", surname: "Owl", age: 38 }
];
let modified = results.map(({name, surname}) => ({name, surname}));
console.log(modified);

Javascript filter array based on another array of object

I am trying to merge the two arrays based on Arr1 values. If the array 2 doesn't has the respective value in array1, it should return as empty object with values. Below are the two arrays:
Arr1 = [{
name: "raj",
age: 20
}, {
name: "ravi",
age: 40
}];
Arr2 = ['raj', 'ravi', 'arnold'];
Javascript Code is,
let result = Arr1.filter(o1 => Arr2.some(o2 => o2 === o1.name));
I am getting the result as below,
result = [{
name: "raj",
age: 20
}, {
name: "ravi",
age: 40
}];
But expected array should be,
[{
name: "raj",
age: 20
}, {
name: "ravi",
age: 40
}, {
name: "arnold",
age: null,
available: no
}];
Any suggestions?
You can use Array#map along with Array#find to obtain your expected result.
let Arr1 = [{
name: "raj",
age: 20
}, {
name: "ravi",
age: 40
}];
let Arr2 = ['raj', 'ravi', 'arnold'];
let result = Arr2.map(x=>
Arr1.find(({name})=>name===x)??{name:x,age:null,available: 'no'}
);
console.log(result);
I suggest a different approach and take an object for the given data and map the wanted names for eithe the given data or a new object.
This approach has a better big O, becaus it take a hash table and works fast for great data.
const
array1 = [{ name: "raj", age: 20 }, { name: "ravi", age: 40 }],
array2 = ['raj', 'ravi', 'arnold'],
data = array1.reduce((r, o) => (r[o.name] = o, r), {}),
result = array2.map(name => data[name] || { name, age: null, available: 'no' });
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to edit object array?

I want to edit JavaScript object.
I have an JavaScript object like this
data_without_id = [
0: {id: 1, name: "Mary", age: null}
1: {id: 2, name: "Bob", age: 33}
2: {id: 1, name: "Kelly", age: 40}
]
I want to convert this object into this
data_without_id = [
0: {id: 1, name: "Kelly", age: 40}
1: {id: 2, name: "Bob", age: 33}
]
What I need to do is:
Group by id
Get latest value.
I tried using Array.prototype.reduce(), but I can't get the result I need...
Using the function reduce would be as follow:
The function reduce for grouping and the function Object.values for extracting the values.
let data_without_id = [ { id: 1, name: "Mary", age: null }, { id: 2, name: "Bob", age: 33 }, { id: 1, name: "Kelly", age: 40 }],
result = Object.values(data_without_id.reduce((a, {id, name, age}) => {
a[id] = {id, name, age};
return a;
}, Object.create(null)));
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could use .reduce by making the accumulator an object that has keys of the id. This way you can overwrite any previously seen objects which had the same id, and then use Object.values to get your array of objects:
const data_without_id = [{id: 1, name: "Mary", age: null}, {id: 2, name: "Bob", age: 33}, {id: 1, name: "Kelly", age: 40}],
res = Object.values(data_without_id.reduce((acc, obj) =>
(acc[obj.id] = obj, acc)
, {}));
console.log(res);
You could just simply use a for/of loop to create a copy of the data where the last object with a particular id will always be the object returned in the output data. This avoids the "grouping" part of the code but still returns the correct data.
const data_without_id = [
{ id: 1, name: "Mary", age: null },
{ id: 2, name: "Bob", age: 33 },
{ id: 1, name: "Kelly", age: 40 }
];
function lastId(arr) {
const out = [];
for (let obj of arr) {
// If you don't create a copy of each object the returned
// data will simply be contain _references_ to the original
// data. Changes in the original data will be reflected
// in the returned data
out[obj.id - 1] = { ...obj };
}
return out;
}
const lastIds = lastId(data_without_id);
console.log(lastIds);

Categories

Resources