lodash filter by name - javascript

I'm trying to figure out how to use lodash to filter the following object:
contacts = {
A: [
{ name: "Albert", age: 16 },
{ name: "Arthur", age: 24}
],
B: [
{ name: "Bob", age: 33 }
],
C: [],
D: [],
...
};
I'd like to be able to filter contacts by name (contains) while keeping the same structure, I don't know to tell lodash to look for any objects on the 2nd level.
Any idea how to go about this?

Try this one
const contacts = {
A: [
{ name: "Albert", age: 16 },
{ name: "Arthur", age: 24}
],
B: [
{ name: "Bob", age: 33 },
{ name: "Ahn", age: 20 },
],
C: [],
D: []
};
const obj = {};
Object.keys(contacts).forEach(index => {
obj[index] = contacts[index].filter(person =>
person.name.includes("th"));
});
console.log(obj);

Use map and filter
var nameToSearch = "Bob";
contacts = Object.keys(contacts).map( s => contacts[s].filter( t => t.name == nameToSearch ) );

Related

Lodash how to group array of objects by array of values?

I want to group an array of objects based on a property which has an array of values,and i want to return a group for each individual value,not only for the whole array.
For example :
let crew = [
{
name:"john",
job :["electrician","carpenter"]
},
{
name: "bill",
job: ["electrician"]
},
{
name: "mark",
job: [ "carpenter"]
}
]
let groupedCrew = _.groupBy(crew,"job")
console.log(groupedCrew)
/*
carpenter:
[
{
job:
[
carpenter
],
name:
"mark"
}
],
electrician:
[
{
job:
[
"electrician"
],
name:
"bill"
}
],
electrician, carpenter:
[
{
job:
[
"electrician",
"carpenter"
],
name:
"john"
}
]
}
*/
In this example i want "john" to also appear in "electrician" group.
Any ideas ?
Once again let's group something using reduce
Here's the basic structure (plus the solution)
let crew = [{
name: "john",
job: ["electrician", "carpenter"]
},
{
name: "bill",
job: ["electrician"]
},
{
name: "mark",
job: ["carpenter"]
}
];
var obj = crew.reduce(function(agg, item) {
// grouping logic below this line
item.job.forEach(function(job) {
agg[job] = agg[job] || []
// agg[job].push (item);
// lets push only name so we can see output
agg[job].push(item.name)
})
// grouping logic above this line
return agg
}, {})
console.log(obj)
use custom .reduce() function
there is no need for lodash
const crew = [
{
name: 'john',
job: ['electrician', 'carpenter'],
},
{
name: 'bill',
job: ['electrician'],
},
{
name: 'mark',
job: ['carpenter'],
},
];
const groupedCrew = crew.reduce((groupedCrew, person) => {
person.job.forEach(job => {
if (!groupedCrew[job]) groupedCrew[job] = [];
groupedCrew[job].push(person);
});
return groupedCrew;
}, {});
console.log(JSON.stringify(groupedCrew, null, 4));

How to return an array with the first 2 elements in an object and iterate until the end

I just want to return an array containing the first and second objects of the element.
The next 2 elements will be repeated after traversing the keys
Given the following object:
const object = {
a: [
{ name: "John", age: 32 },
{ name: "David", age: 23 },
{ name: "Justin", age: 28 },
{ name: "Arnauld", age: 35 }
],
b: [
{ name: "Ivan", age: 18 },
{ name: "Nekko", age: 13 },
{ name: "Lena", age: 25 }
],
c: [
{ name: "Ann", age: 19 },
{ name: "Nick", age: 14 }
]
};
the result I want is
[
{ name: "John", age: 32 },
{ name: "David", age: 23 },
{ name: "Ivan", age: 18 },
{ name: "Nekko", age: 13 },
{ name: "Ann", age: 19 },
{ name: "Nick", age: 14 },
{ name: "Justin", age: 28 },
{ name: "Arnauld", age: 35 },
{ name: "Lena", age: 25 }
]
You can use Object.values() and then you can use array.reduce() to get desire values.
const object = {
a: [
{ name: "John", age: 32 },
{ name: "David", age: 23 },
{ name: "Justin", age: 28 },
{ name: "Arnauld", age: 35 }
],
b: [
{ name: "Ivan", age: 18 },
{ name: "Nekko", age: 13 },
{ name: "Lena", age: 25 }
],
c: [
{ name: "Ann", age: 19 },
{ name: "Nick", age: 14 }
]
};
let newArray = Object.values(object).reduce((prev, current) => ([...prev, ...current.slice(0,2)]),[]);
console.log(newArray)
const object = {
a: [
{ name: "John", age: 32 },
{ name: "David", age: 23 },
{ name: "Justin", age: 28 },
{ name: "Arnauld", age: 35 }
],
b: [
{ name: "Ivan", age: 18 },
{ name: "Nekko", age: 13 },
{ name: "Lena", age: 25 }
],
c: [
{ name: "Ann", age: 19 },
{ name: "Nick", age: 14 }
]
};
const result = Object.values(object).reduce((acc, cur) => {
const arr = cur.map((item, index) => {
return { ...item, index: Math.floor(index / 2) };
});
return [...acc, ...arr];
}, []).sort((a,b) => a.index - b.index);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0 }
this gives exact the order as you requested it.
EDIT
Explanation:
The solution iterates over Object.values() array and uses .reduce() in order to first assign an index to each element (in the arrays corresponding to keys a, b, c.
Then, it uses .sort() to obtain the desired order in the resulting array.
const names = [];
while (true) {
let test = false;
for (const [key, value] of Object.entries(object)) {
if (value.length > 0) {
const arrays = value.splice(0, 2)
names.push(...arrays)
test = true
}
}
if (test === false) break;
}
console.log(names);
i think something like this will do, but be careful using splice because it'll delete the values from the array
Or try This shorter approach:
let result = [];
Object.entries(object).map((item) => {
result.push(item[1][0], item[1][1]);
});
// This will return your desired result
console.log(result)
Calling Object.entries() generate an array with all its enumerable properties.
Presented below is one possible way to achieve the desired objective.
Code Snippet
const myTransform = obj => (
Object.values(obj)
.reduce(
(acc, itm) => (
acc.concat(
itm.map(
(elt, idx) => ({
...elt,
index: Math.floor(idx / 2)
})
)
)
),
[]
)
.sort(
(
{index : aIdx},
{index: bIdx}
) => aIdx - bIdx
)
.map(
(
{index, ...rest}
) => ({...rest})
)
);
/*
// method to transform object into desired array
const myTransform = obj => (
// extract the values of the object, as an array
Object.values(obj)
// iterate over the values using ".reduce()"
.reduce(
// "acc" is the accumulator, "itm" is iterator/item
(acc, itm) => (
// concat result of inner-expression to "acc"
acc.concat(
// iterate over "itm" array
itm.map(
// for each object, add "index" as a prop
(elt, index) => ({
...elt,
// value of index is ".floor()" of index/position / 2
// this ensures all elts in 0, 1 are with index 0
// and elts in 2, 3 are with index 1, so on...
index: Math.floor(idx / 2)
}) // implicit return for ".map()"
)
)
),
[] // "acc" is initially set to "[]" empty-array
)
.sort(
// now, we have "index" - so use that to ".sort()"
(
{index: aIdx}, // destructure & rename index
{index: bIdx}
) => aIdx - bIdx // return 0, positive or negative to determine sort order
)
// finally, remove the ".index" introduced in above code
.map(
( // destructure to access "index" separately
{index, ...rest}
) => ({...rest}) // return only props other than "index"
)
);
*/
const object = {
a: [
{ name: "John", age: 32 },
{ name: "David", age: 23 },
{ name: "Justin", age: 28 },
{ name: "Arnauld", age: 35 }
],
b: [
{ name: "Ivan", age: 18 },
{ name: "Nekko", age: 13 },
{ name: "Lena", age: 25 }
],
c: [
{ name: "Ann", age: 19 },
{ name: "Nick", age: 14 }
]
};
/*const result = Object.values(object).reduce((acc, cur) => {
const arr = cur.map((item, index) => {
return { ...item, index: Math.floor(index / 2) };
});
return [...acc, ...arr];
}, []).sort((a,b) => a.index - b.index);*/
console.log(myTransform(object));
.as-console-wrapper { max-height: 100% !important; top: 0 }
Explanation
Inline comments added to the snippet above.

Grouping Arrays By Nested Arrays

I have the following array that I'd like to transform into an Object with unique hobbies as the keys
const arr = [
{ name: 'Joe', hobbies: ['skating', 'biking', 'music'] },
{ name: 'Kim', hobbies: ['fishing', 'biking', 'karate'] },
{ name: 'Ben', hobbies: ['surfing'] },
]
I use lodash's handy groupBy function but it groups the multiple array elements into single keys like so
{
'skating,biking,music': [
{ name: 'Joe' }
],
'fishing,biking,karate': [
{ name: 'Kim' }
],
'surfing': [
{ name: 'Ben' }
],
}
What I need is the following output (note the objects are repeated for each of their respective hobbies)
{
biking: [
{ name: 'Joe' },
{ name: 'Kim' }
],
skating: [
{ name: 'Joe' }
],
karate: [
{ name: 'Kim' }
],
surfing: [
{ name: 'Ben' }
],
...
}
Is there a simple way to group this array without looping through each array element, splitting them up and regrouping? Would like to avoid this if there's better utility method out there I'm unaware of
You can iterate each item and each hobbie and then add it to a result object:
const arr = [
{ name: 'Joe', hobbies: ['skating', 'biking', 'music'] },
{ name: 'Kim', hobbies: ['fishing', 'biking', 'karate'] },
{ name: 'Ben', hobbies: ['surfing'] }
]
const result = {};
arr.forEach(item =>
item.hobbies.forEach(hobbie =>
result[hobbie] = (result[hobbie] || []).concat({name: item.name})
)
)
console.log(result);
const arr = [
{ name: 'Joe', hobbies: ['skating', 'biking', 'music'] },
{ name: 'Kim', hobbies: ['fishing', 'biking', 'karate'] },
{ name: 'Ben', hobbies: ['surfing'] }
]
const result = {};
arr.forEach(item =>
item.hobbies.forEach(hobbie =>
result[hobbie] = result[hobbie]?[...result[hobbie],{name: item.name}]: [{name: item.name}]
)
)
console.log(result);
I've renamed arr to people for better understanding.
const people = [
{ name: 'Joe', hobbies: ['skating', 'biking', 'music'] },
{ name: 'Kim', hobbies: ['fishing', 'biking', 'karate'] },
{ name: 'Ben', hobbies: ['surfing'] },
];
function transform(people) {
// get all hobbies and remove duplicates
const hobbies = [... new Set(
people.reduce((hobbies, person) => hobbies.concat(person.hobbies), [])
)];
const res = {};
// take a hobby and use it as key
for (let hobby of hobbies) {
res[hobby] = people
.filter((person) => person.hobbies.includes(hobby))
.map((person) => { return { name: person.name }; });
}
return res;
}
console.log(transform(people));

How to remove a property from array of objects [duplicate]

This question already has answers here:
Remove property for all objects in array
(18 answers)
Closed 1 year ago.
I have an array of objects with name and age property:
[
{ name: "Matthew", age: 23 },
{ name: "James", age: 20 },
{ name: "Daniel", age: 25 },
{ name: "Joshua", age: 22 }
]
I want to remove age property from all of the objects and print in console like
[
{ name: "Matthew" },
{ name: "James" },
{ name: "Daniel" },
{ name: "Joshua" }
]
Iterate over your array and use delete keyword.
let array = [
{ name: "Matthew", age: 23 },
{ name: "James", age: 20 },
{ name: "Daniel", age: 25 },
{ name: "Joshua", age: 22 }
]
array.forEach(function(v){ delete v.age });
console.log(array);
You can use map function to achieve this.
let output = test.map(({name}) => ({name}));
If you want to filter with multiple object you can add after name like {name, salary}
var test =[
{ name: "Matthew", age: 23 },
{ name: "James", age: 20 },
{ name: "Daniel", age: 25 },
{ name: "Joshua", age: 22 }
];
let output = test.map(({name}) => ({name}));
console.log(JSON.stringify(output, null, 2));
const newData = oldData.map(item=>({name:item.name}))

How to turn my single object into an iterable instance so I can merge it with another array?

I have a single object and an array of objects and now I'm trying to merge them using the spread operator like this:
let singleObject = { name: 'John', age: 20 }
let arrayOfObjects = [
{ name: 'Ben', age: 25 },
{ name: 'Casey', age: 30 }
]
let mergedArray = [...singleObject, ...arrayOfObjects];
However, this doesn't work since singleObject is just an object, whereas, arrayOfObjects is an array of objects.
So I'm wondering if I should use a different way to merge the object with the array or if I should just make the object iterable somehow?
You can change
let mergedArray = [...singleObject, ...arrayOfObjects];
to
let mergedArray = [{...singleObject}, ...arrayOfObjects];
Or
let mergedArray2 = Object.assign([], singleObject, ...arrayOfObjects);
let singleObject = { name: 'John', age: 20 }
let arrayOfObjects = [
{ name: 'Ben', age: 25 },
{ name: 'Casey', age: 30 }
]
let mergedArray = [{...singleObject}, ...arrayOfObjects];
console.log(mergedArray)
let mergedArray2 = Object.assign([], [singleObject, ...arrayOfObjects]);
console.log(mergedArray2)
You can just push yopur object into array like this, instead of concatinate
let singleObject = { name: 'John', age: 20 }
let arrayOfObjects = [
{ name: 'Ben', age: 25 },
{ name: 'Casey', age: 30 }
]
arrayOfObjects.push(singleObject);
console.log(arrayOfObjects);
You can use Array.of as follows:
let singleObject = { name: 'John', age: 20 }
let arrayOfObjects = [
{ name: 'Ben', age: 25 },
{ name: 'Casey', age: 30 }
]
let mergedArray = [...Array.of(singleObject), ...arrayOfObjects];
console.log(mergedArray);
Try this
let singleObject = { name: 'John', age: 20 }
let arrayOfObjects = [
{ name: 'Ben', age: 25 },
{ name: 'Casey', age: 30 }
]
let mergedArray = [{...singleObject}, ...arrayOfObjects];
console.log(mergedArray);

Categories