How to create a new array from child object properties - javascript

I have an array:
[
{
meta:'abc'
data:
{
name:'asd',
title: 'bbb'
}
},
{
meta:'abc'
data:
{
name:'asd',
title: 'bbb'
},
{
meta:'abc'
data:
{
name:'asd',
title: 'bbb'
}
}
]
I want to convert it to new array, which will be:
[
{
name:'asd',
title: 'bbb'
},
{
name:'asd',
title: 'bbb'
{
name:'asd',
title: 'bbb'
}
]
I want to take only the data elements, and to create from them a new array.
How can I do it the fastest way? And how can I do it with lodash?
Thanks!

You can use _.map
var array = [{
meta: 'abc',
data: {
name: 'asd',
title: 'bbb'
}
}, {
meta: 'abc',
data: {
name: 'asd',
title: 'bbb'
}
}, {
meta: 'abc',
data: {
name: 'asd',
title: 'bbb'
}
}];
console.log(_.map(array, 'data'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.2.0/lodash.js"></script>

Just you need is the map() native javascript method to arrays:
//considere that 'someArray' is the same as your.
var newArray = someArray.map(function(item){
return {name: item.data.name, title: item.data.title};
});

Related

Filter does not return the correct result

I have this array and I created this function that return me the filtered array:
const result = [{
key: 'A',
title: 'titleA',
data: [{
name: 'miael',
id: 'id4',
},
{
name: 'top',
id: 'id2',
}
]
},
{
key: 'B',
title: 'titleB',
data: [{
name: 'mich1',
id: 'id12',
},
{
name: 'tomato',
id: 'id123',
}
]
},
]
const doSearch = (data) => result.filter(entry =>
entry.data.some(item =>
item.name
.toString()
.toLowerCase()
.includes(data.toString().toLowerCase().trim()),
),
);
console.log(doSearch('mich'));
This works, but it also returns results that do not contain the searched word 'mic'
if I search for mic, I expect this result:
[{
key: 'B',
title: 'titleB',
data: [{
name: 'mich1',
id: 'id12',
},
]
}],
what am I doing wrong?
A couple of changes should make this work the way you wish.
Turning doSearch into a function.
Adding a searchFor parameter to the doSearch() function and passing to the .includes() call.
Using Array.reduce() to create the output array. Items are only added if they include the searchFor value.
const input = [{ key: 'A', title: 'titleA', data: [{ name: 'miael', id: 'id4', }, { name: 'top', id: 'id2', } ] }, { key: 'B', title: 'titleB', data: [{ name: 'mich1', id: 'id12', }, { name: 'tomato', id: 'id123', } ] }, ]
const doSearch = (searchFor, arr) => arr.reduce((acc, { key, title, data }) => {
const filteredData = data.filter(({ name }) => {
return name.toLowerCase().includes(searchFor.toLowerCase())
});
if (filteredData.length > 0) {
acc.push({ key, title, data: filteredData });
}
return acc;
}, []);
console.log(doSearch('mic', input ));
You can keep your current logic and add a map with the same filter for entry.data:
const result = [{
key: 'A',
title: 'titleA',
data: [{
name: 'miael',
id: 'id4',
},
{
name: 'top',
id: 'id2',
}
]
},
{
key: 'B',
title: 'titleB',
data: [{
name: 'mich1',
id: 'id12',
},
{
name: 'tomato',
id: 'id123',
}
]
},
]
function nameFilter(item, data) {
return item.name
.toString()
.toLowerCase()
.includes(data.toString().toLowerCase().trim())
}
const doSearch = (data) => result.filter(entry =>
entry.data.some(item =>
nameFilter(item, data)
),
).map(entry => ({
...entry,
data: entry.data.filter(item => nameFilter(item, data))
}));
console.log(doSearch('mich'));

How to format complicated array with ._groupBy

My array looks like, but includes 1000+ objects:
data = {
0: {
code: '3019476',
_id: '60033f61-8a4e-4622-9731-decd07bc44e1',
vendor: 'DKNY',
tags: [
{ type: 1, label: 'dsfs' },
{ type: 2, label: 'thisOne' },
{ type: 3, label: 'sdas' },
],
},
1: {
code: '3019475',
_id: '60033f61-8a4e-4622-9731-decd07bc44e0',
vendor: 'DKNY',
tags: [
{ type: 1, label: 'sdfsd' },
{ type: 2, label: 'anotherOne' },
{ type: 3, label: 'sdfsd' },
],
},
2: {
code: '3019474',
_id: '60033f61-8a4e-4622-9731-decd07bc44e9',
vendor: 'DKNY',
tags: [
{ type: 1, label: 'gregf' },
{ type: 2, label: 'thisOne' },
{ type: 3, label: 'gregf' },
],
},
};
I expect this as output:
0: {title: "thisOne", data: Array(2)"}
1: {title: "anotherOne", data: Array(1)"}
So I want to filter and count how many objects include different tag[1].label, saving full item data in 'data' inside result.
All my ideas failed, so I really need your help
I suspect that you are looking for groupBy with a property path iteratee shorthand:
import { groupBy } from 'underscore';
groupBy(data, ['tags', 1, 'label']);
// { thisOne: [Object, Object],
// anotherOne: [Object]
// }
This produces an object with the labels as keys and the groups as values. From here, it is easy to get it in the exact shape of the example output from your question, for example using chain and map:
import { chain } from 'underscore';
chain(data)
.groupBy(['tags', 1, 'label'])
.map((data, title) => ({data, title}))
.value();
// [ { title: 'thisOne', data: [Object, Object] },
// { title: 'anotherOne', data: [Object] }
// ]
There are a lot of syntax error in data, fix them and it should work. See the code snippet below.
NOTE: Key/Value pairs in an object should separated with commas and dsfs, thisOne sdas should be valid variables or strings.
data = {
0: {
code: '3019476',
_id: '60033f61-8a4e-4622-9731-decd07bc44e1',
vendor: 'DKNY',
tags: [
{ type: 1, label: 'dsfs' },
{ type: 2, label: 'thisOne' },
{ type: 3, label: 'sdas' },
],
},
1: {
code: '3019475',
_id: '60033f61-8a4e-4622-9731-decd07bc44e0',
vendor: 'DKNY',
tags: [
{ type: 1, label: 'sdfsd' },
{ type: 2, label: 'anotherOne' },
{ type: 3, label: 'sdfsd' },
],
},
2: {
code: '3019474',
_id: '60033f61-8a4e-4622-9731-decd07bc44e9',
vendor: 'DKNY',
tags: [
{ type: 1, label: 'gregf' },
{ type: 2, label: 'thisOne' },
{ type: 3, label: 'gregf' },
],
},
};
console.log(data[0].tags[1].label)
You don't need lodash for that. You can use plain javascript.
const data= [
{code: "3019476", _id: "60033f61-8a4e-4622-9731-decd07bc44e1", vendor: "DKNY", tags: [{type: 1, label: 'dsfs'},{type: 2, label: 'thisOne'},{type: 3, label: 'sdas'}]}, {code: "3019475", _id: "60033f61-8a4e-4622-9731-decd07bc44e0", vendor: "DKNY", tags: [{type: 1, label: 'sdfsd'},{type: 2, label: 'anotherOne'},{type: 3, label: 'sdfsd'}]}, {code: "3019474", _id: "60033f61-8a4e-4622-9731-decd07bc44e9", vendor: "DKNY", tags: [{type: 1, label: 'gregf'},{type: 2, label: 'thisOne'},{type: 3, label: 'gregf'}]}]
const newData = data.map(d => {
let result = {};
result.title = d.tags.find(tag => tag.type === 2).label;
result.data = d.tags.filter(tag => tag.type === 2);
return result;
});
console.log(newData);
P.S.: This snippet is considering that more than one tagType can be included into the data array and that the first found will be used as title.
If that is not what you want then the question should be clearer.

How to group object inside array

Here is what I have
[
{
typeProgramId: {
name: 'type1',
},
title: 'test1',
},
{
typeProgramId: {
name: 'type1',
},
subTypeProgramId: [{
name: 'sub1',
}],
title: 'test2',
},
{
typeProgramId: {
name: 'type2',
},
title: 'test3',
},
{
typeProgramId: {
name: 'type2',
},
subTypeProgramId: {
name: 'sub2',
},
title: 'test4',
}
]
First I want to group typeProgramId if the title have the same typeProgramId I want to push title into array by each typeProgramId but If the data have typeProgramId and subTypeProgram Id I want to group subtypeProgramId in typeProgramId too. if not empty subtypeProgramId I want to push it in array title inside subtypeProgram Id. I try to use lodash groupBy and many way but it still did not work.
Here is what I want
{
typeProgramId: [{
name: 'type1',
title: [
'test1',
],
subTypeProgramId: {
name: sub1,
title: [
'test2'
]
}
}, {
name: 'type2',
title: [
'test3',
],
subTypeProgramId: [{
name: sub1,
title: [
'test4'
]
}
}]
}
what I do now
let result = _.groupBy(getProgram, function(data) {
return data.typeProgramId
})
result = _.map(result, function(group, data) {
// I think in here I must groupBy subTypeProgramId again
// the data return all string not object after group
return {
typeProgramId: data,
titile: group,
}
})
Please check the below code. I have used reduce function of Array. It produces the expected result.
function updateMem(mem, prgIndex, val){
if(prgIndex < 0) {
mem.typeProgramId.push({});
prgIndex = mem.typeProgramId.length - 1;
}
mem.typeProgramId[prgIndex].name = val.typeProgramId.name;
if(val.subTypeProgramId){
mem.typeProgramId[prgIndex].subTypeProgramId = Object.assign({}, mem.typeProgramId[prgIndex].subTypeProgramId || {}, {"name" : val.subTypeProgramId.name, "title": []});
mem.typeProgramId[prgIndex].subTypeProgramId.title.push(val.title);
} else {
mem.typeProgramId[prgIndex].title = (mem.typeProgramId[prgIndex].title ? mem.typeProgramId[prgIndex].title : []);
mem.typeProgramId[prgIndex].title.push(val.title);
}
};
arr.reduce((mem, val) => {
var prgIndex = mem.typeProgramId.findIndex((p) => p.name === val.typeProgramId.name);
updateMem(mem, prgIndex, val);
return mem;
}, {typeProgramId: []});

how to extract objects from array of object based on similar id

I have created this sample code , to explain what i am tring to do .
arr = [
{ id:1 , name:'a', title: 'qmummbw' },
{ id:2 , name:'b', title: 'sdmus' },
{ id:2 , name:'', title: 'dvfv' },
{ id:3 , name:'c', title: 'dujuw' },
{ id:1 , name:'d', title: 'ccnyu' },
{ id:4 , name:'e', title: 'tjtjn' },
{ id:4 , name:'f', title: 'tryr' },
{ id:1 , name:'g', title: 'gbgfbgf' },
{ id:2 , name:'h', title: 'tgrtg' },
{ id:3 , name:'i', title: 'fdvd' },
{ id:1 , name:'j', title: 'dsnyc' },
{ id:1 , name:'k', title: 'nyuny' }
];
array = [];
allArray = [];
for (i = 0; i < arr.length; i++) {
for (j = i + 1; j < arr.length; j++) {
if (arr[i].id === arr[j].id) {
if (!array.includes(arr[i])) {
array.push(arr[i], arr[j]);
} else {
array.push(arr[j]);
}
allArray.push(array);
array = []
}
}
}
console.log(allArray);
Output i am getting is:
[[{
id: 1,
name: "a",
title: "qmummbw"
}, {
id: 1,
name: "d",
title: "ccnyu"
}], [[circular object Object], {
id: 1,
name: "g",
title: "gbgfbgf"
}], [[circular object Object], {
id: 1,
name: "j",
title: "dsnyc"
}], [[circular object Object], {
id: 1,
name: "k",
title: "nyuny"
}], [{
id: 2,
name: "b",
title: "sdmus"
}, {
id: 2,
name: "",
title: "dvfv"
}], [[circular object Object], {
id: 2,
name: "h",
title: "tgrtg"
}], [[circular object Object], [circular object Object]], [{
id: 3,
name: "c",
title: "dujuw"
}, {
id: 3,
name: "i",
title: "fdvd"
}], [[circular object Object], [circular object Object]], [[circular object Object], [circular object Object]], [[circular object Object], [circular object Object]], [{
id: 4,
name: "e",
title: "tjtjn"
}, {
id: 4,
name: "f",
title: "tryr"
}], [[circular object Object], [circular object Object]], [[circular object Object], [circular object Object]], [[circular object Object], [circular object Object]]]
My main goal is to get the array of object , each object containing the same id together and keeping in mind that the arr = [] can have n no of data.
You could group by id and take the values form the object, if necessary.
const
array = [{ id: 1 , name: 'a', title: 'qmummbw' }, { id: 2 , name: 'b', title: 'sdmus' }, { id: 2 , name: '', title: 'dvfv' }, { id: 3 , name: 'c', title: 'dujuw' }, { id: 1 , name: 'd', title: 'ccnyu' }, { id: 4 , name: 'e', title: 'tjtjn' }, { id: 4 , name: 'f', title: 'tryr' }, { id: 1 , name: 'g', title: 'gbgfbgf' }, { id: 2 , name: 'h', title: 'tgrtg' }, { id: 3 , name: 'i', title: 'fdvd' }, { id: 1 , name: 'j', title: 'dsnyc' }, { id: 1 , name: 'k', title: 'nyuny' }],
grouped = array.reduce((r, o) => ((r[o.id] = r[o.id] || []).push(o), r), {});
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use the reduce method like this:
const filteredArray = arr.reduce((acc, el) => {
if (acc[el.id] || (acc[el.id] = [])) {
acc[el.id].push(el);
}
return acc;
}, {});
var arr = [
{ id:1 , name:'a', title: 'qmummbw' },
{ id:2 , name:'b', title: 'sdmus' },
{ id:2 , name:'', title: 'dvfv' },
{ id:3 , name:'c', title: 'dujuw' },
{ id:1 , name:'d', title: 'ccnyu' },
{ id:4 , name:'e', title: 'tjtjn' },
{ id:4 , name:'f', title: 'tryr' },
{ id:1 , name:'g', title: 'gbgfbgf' },
{ id:2 , name:'h', title: 'tgrtg' },
{ id:3 , name:'i', title: 'fdvd' },
{ id:1 , name:'j', title: 'dsnyc' },
{ id:1 , name:'k', title: 'nyuny' }
],
result = Object.values(arr.reduce(function (r, a) {
r[a.id] = r[a.id] || [];
r[a.id].push(a);
return r;
}, Object.create(null))).map(e => e);
console.log([result]);

Use lodash to group array into tree "children" structure

Using lodash, I need to convert the following array:
[{
text: 'apple',
type: 'fruit'
}, {
text: 'pear',
type: 'fruit',
}, {
text: 'potato',
type: 'vegetable'
}, {
text: 'water',
type: 'beverage'
}]
Into the following format:
[{
text: 'fruit',
children: [{
text: 'apple',
type: 'fruit'
}, {
text: 'pear',
type: 'fruit'
}]
}, {
text: 'vegetable',
children: [{
text: 'potato',
type: 'vegetable'
}]
}, {
text: 'beverage',
children: [{
text: 'water',
type: 'beverage'
}]
}]
I've attempted to chain lodash methods like groupBy and transform, but am having a hard time getting to the resulting format I require.
Here's a skeleton of what direction I was heading:
_(arr).groupBy('type').transform(function(result, obj, type) {
return result.push({
name: type,
children: obj
});
}).value();
The issue I'm running into is groupBy turns my array into an Object, so I can no longer simply push onto an Array. Being relatively knew with lodash (around 4 or 5 months of experience), I wanted to see if others have already tackled such a requirement.
Use _.reduce() instead of transform, because it lets you state the end product format:
var arr = [{
text: 'apple',
type: 'fruit'
}, {
text: 'pear',
type: 'fruit',
}, {
text: 'potato',
type: 'vegetable'
}, {
text: 'water',
type: 'beverage'
}];
var results = _(arr)
.groupBy('type')
.reduce(function(array, children, key) {
array.push({
text: key,
children: children
});
return array;
}, []);
console.log(results);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>

Categories