how to flatten out the array and assign new keys? (TS, JS) - javascript

From this long JSON file, I want to pick few keys and values.
[{
c_id: "1",
c: "google",
displayName: "display name",
myResults: [{ //type: Array<MyResult>
type: 'TEXT',
name: 'my text',
label: 'my RealText',
id: '2',
description: 'sdf'
}, {
type: 'STRING',
name: 'my text',
label: 'my sdf',
id: '3',
description: 'sdf',
}
],
fieldValues: 'Object',
id: "d-ss-dd-asda-sdcv",
index: 0,
name: "google",
type: "NAH",
},
{
c_id: "sddc-ss",
connector: "facebook",
displayName: "d f d",
myFields: [],
myResults: [{ //type: Array<MyResult>
type: 'TEXT',
name: 'my text',
label: 'my RealText',
id: '5',
description: 'sdf'
}, {
type: 'STRING',
name: 'my text',
label: 'my sdf',
id: '6',
description: 'sdf',
}
],
fieldValues: 'Object',
id: "s-sdf-sdfdc",
index: 1,
name: "action",
type: "ACTION"
}];
Output
[{
id: "d-ss-dd-asda-sdcv", //c_id
label: 'google' //c
index: 0
}, {
id: '2',
label: 'my RealText',
}, {
id: '3',
label: 'my sdf',
}, {
id: "sddc-ss", //c_id
label: 'facebook' //c
index: 0
}, {
id: '5',
label: 'my RealText',
}, {
id: '6',
label: 'my sdf',
}]
How do I make this work using flatList?
input.flatMap(({ myResults, ...item }) => [item, ...myResults])

const result = data.flatMap(({ c_id, c, index, myResults }) => ([
{ id: c_id, label: c, index },
...myResults.map(({ id, label }) => ({ id, label }))
]))
Maybe this would work, but I'm just guessing because your data seems inconsistent. c_id and id seem to get switched, google is the "c" key but facebook is the "connector key"

Related

Push value to multiple arrays

const array = [{
id: 1,
name: 'test',
attrs: [{
name: 'Attribute 1',
description: 'Description 1',
}],
values: [{
name: 'value 1',
attrs: [{
name: 'Attribute 1',
type: 'Type 1',
},
{
name: 'Attribute 2',
type: 'Type 2',
},
],
}, ],
}, ];
const newArray =
array.map((item) => {
return {
...item,
isNegative: true
};
});
console.log(newArray);
I receive data as displayed in the const array. I need to push a value 'isNegative' to array[].attrs and to each values.attrs. I'm only able to do it to the array[].attrs. How can I do it to the others?
You're only mapping over the top-level array. If you need to map over the arrays within each object, that's another call to .map(). For example:
const array = [{
id: 1,
name: 'test',
attrs: [{
name: 'Attribute 1',
description: 'Description 1',
}],
values: [{
name: 'value 1',
attrs: [{
name: 'Attribute 1',
type: 'Type 1',
},
{
name: 'Attribute 2',
type: 'Type 2',
},
],
}, ],
}, ];
const newArray =
array.map((item) => {
return {
...item,
isNegative: true,
attrs: item.attrs.map((attr) => {
return {
...attr,
isNegative: true
}
})
};
});
console.log(newArray);
Same with the values property, any array within objects in values, etc. Any array that you want to map to a new structure, call .map() on it.

Is there a way to concatenate parent's value in array of deep nested objects

I have an array of nested objects. I need to update the id property of each node by concatenating all its parent names.
id should be value of the name property of current node joined with name property
od it's parents separated by '/'
treeData = [{
name: 'Infiniti',
id: '',
children: [{
name: 'G50',
id: '',
children: [{
name: 'Pure AWD',
id: ''
},
{
name: 'Luxe',
id: ''
},
],
},
{
name: 'QX50',
id: '',
children: [{
name: 'Pure AWD',
id: ''
},
{
name: 'Luxe',
id: ''
},
],
},
],
},
{
name: 'BMW',
id: '',
children: [{
name: '2 Series',
id: '',
children: [{
name: 'Coupé',
id: ''
},
{
name: 'Gran Coupé',
id: ''
},
],
},
{
name: '3 Series',
id: '',
children: [{
name: 'Sedan',
id: ''
},
{
name: 'PHEV',
id: ''
},
],
},
],
},
];
Expected Outcome
[{
name: 'Infiniti',
id: 'Infiniti',
children: [{
name: 'G50',
id: 'Infiniti/G50',
children: [{
name: 'Pure AWD',
id: 'Infiniti/G50/Pure AWD'
},
{
name: 'Luxe',
id: 'Infiniti/G50/Luxe'
},
],
},
{
name: 'QX50',
id: 'Infiniti/QX50',
children: [{
name: 'Pure AWD',
id: 'Infiniti/QX50/Pure AWD'
},
{
name: 'Luxe',
id: 'Infiniti/QX50/Luxe'
},
],
},
],
},
{
name: 'BMW',
id: 'BMW',
children: [{
name: '2 Series',
id: 'BMW/2 Series',
children: [{
name: 'Coupé',
id: 'BMW/2 Series/Coupé'
},
{
name: 'Gran Coupé',
id: 'BMW/2 Series/Gran Coupé'
},
],
},
{
name: '3 Series',
id: 'BMW/3 Series',
children: [{
name: 'Sedan',
id: 'BMW/3 Series/Sedan'
},
{
name: 'PHEV',
id: 'BMW/3 Series/PHEV'
},
],
},
],
},
];
I tried to use Array.prototype.reduce(), but I am unable to get the previous value to concatinate.
function updateTreeData(array) {
return array.reduce((returnValue, currentValue) => {
if (currentValue.children != null) {
returnValue.push(Object.assign({}, currentValue, {
children: this.updateTreeData(currentValue.children)
}))
}
return returnValue
}, []);
}
console.log(updateTreeData(treeData))
You can try the recursion approach
const treeData=[{name:"Infiniti",id:"",children:[{name:"G50",id:"",children:[{name:"Pure AWD",id:""},{name:"Luxe",id:""}]},{name:"QX50",id:"",children:[{name:"Pure AWD",id:""},{name:"Luxe",id:""}]}]},{name:"BMW",id:"",children:[{name:"2 Series",id:"",children:[{name:"Coupé",id:""},{name:"Gran Coupé",id:""}]},{name:"3 Series",id:"",children:[{name:"Sedan",id:""},{name:"PHEV",id:""}]}]}];
const populateId = (list, currentId) => {
for(const item of list) {
if(!currentId) {
item.id = item.name
} else {
item.id = currentId + '/' + item.name
}
if(item.children) {
populateId(item.children, item.id)
}
}
}
populateId(treeData)
console.log(treeData)

How to convert flat array containing a child "path" array into a nested array of objects based on the path?

I have an array of objects, each containing a path property which holds the value of "paths" to which I'd like to map the array elements to.
let myData = [
{
path: ['Movies', 'Comedies', 'TopRanked'],
name: 'The Hangover',
id: '1',
},
{
path: ['Movies', 'Comedies', 'TopRanked'],
name: 'Eurotrip',
id: '2',
},
{
path: ['Movies', 'Action'],
name: 'Need for Speed',
id: '3',
},
{
path: ['Life'],
name: 'Not so bad',
id: '4',
},
{
path: ['Life', 'Financial', 'Income'],
name: 'Making Hundreds',
id: '5',
},
{
path: ['Life', 'Financial', 'Income'],
name: 'Making Thousands',
id: '6',
},
{
path: ['Life', 'MonthlySpent'],
name: 'Just a little bit',
id: '7',
},
{
path: ['Life', 'MonthlySpent'],
name: 'Living large',
id: '8',
},
];
console.log(myData);
Essentially, the result I am looking for is a breakdown of that array into as many as nested arrays as needed (relative to all possible available paths), with each retaining its "type" - either a parent or an item. So the desired output is like so:
let myTree = [
{
name: 'Movies',
type: 'parent',
children: [
{
name: 'Comedies',
type: 'parent',
children: [
{
name: 'TopRanked',
type: 'parent',
children: [
{
name: 'The Hangover',
type: 'item',
id: 1,
path: ['Movies', 'Comedies', 'TopRanked']
},
{
name: 'Eurotrip',
type: 'item',
id: 2,
path: ['Movies', 'Comedies', 'TopRanked'],
}
]
},
]
},
{
name: 'Action',
type: 'parent',
children: [
{
name: 'Need for Speed',
type: 'item',
id: 3,
path: ['Movies', 'Action'],
},
]
}
]
},
{
name: 'Life',
type: 'parent',
children: [
{
name: 'Not so bad',
type: 'item',
id: 4,
path: ['Life'],
},
{
name: 'Financial',
type: 'parent',
children: [
{
name: 'Income',
type: 'parent',
children: [
{
name: 'Making Hundreds',
type: 'item',
id: 5,
path: ['Life', 'Financial', 'Income'],
},
{
name: 'Making Thousands',
type: 'item',
id: 6,
path: ['Life', 'Financial', 'Income'],
}
]
}
]
},
{
name: 'MonthlySpent',
type: 'parent',
children: [
{
name: 'Just a little bit',
type: 'item',
id: 7,
path: ['Life', 'MonthlySpent'],
},
{
name: 'Living Large',
type: 'item',
id: 8,
path: ['Life', 'MonthlySpent'],
}
]
}
]
}
]
console.log(myTree);
I tried the following, and while the tree structure is created, the "item"-types are not placed as the array-value of the last nested "parent" type:
function treeData(data) {
var result = [],
hash = { _: { children: result } };
data.forEach(function (object) {
object.path.reduce(function (o, p) {
if (!o[p]) {
o[p] = { _: { name: p, children: [] } };
o._.children.push(o[p]._);
}
return o[p];
}, hash)._.name = object.name;
});
return result;
}
Would appreciate a working solution, as I am wracking my head and can't find one. Tnnx.
The approach below follows a similar pattern to your code i.e. loop every object, but instead of a reduce simply loops every item in path and creates a branch off the root. When there are no more 'branches' then add the original object. See the comments.
let myData = data();
let myTree = treeData(data);
console.log(myTree);
function treeData(data) {
let root = {"children": []} // create origin
for (obj of myData) { // loop items in the data
obj.type = "Item"; // add a property to suit your output
let tree = root; // start at root every object
for (path of obj.path) { // loop over items in path
let branch = tree.children.find(k => k.name == path); // look for branch
if (!branch) { // if no branch, create one
branch = {"name": path, "type": "parent", "children": []}
tree.children.push(branch); // push this into children of current level
}
tree = branch; // set tree to branch before processing next item in path
}
tree.children.push(obj); // add the item to the hierarchy after path is exhausted
}
return root.children; // return children of the root to suit your output
}
function data() {
return [
{
path: ['Movies', 'Comedies', 'TopRanked'],
name: 'The Hangover',
id: '1',
},
{
path: ['Movies', 'Comedies', 'TopRanked'],
name: 'Eurotrip',
id: '2',
},
{
path: ['Movies', 'Action'],
name: 'Need for Speed',
id: '3',
},
{
path: ['Life'],
name: 'Not so bad',
id: '4',
},
{
path: ['Life', 'Financial', 'Income'],
name: 'Making Hundreds',
id: '5',
},
{
path: ['Life', 'Financial', 'Income'],
name: 'Making Thousands',
id: '6',
},
{
path: ['Life', 'MonthlySpent'],
name: 'Just a little bit',
id: '7',
},
{
path: ['Life', 'MonthlySpent'],
name: 'Living large',
id: '8',
},
];
}
.as-console-wrapper { max-height: 100% !important; top: 0; }

How can I move an object from one array to another array with function?

Hello everyone and dear friends. While learning React, I noticed that I lacked javascript and I started to learn javascript carefully.
Let me try to tell you what I am trying to do. I have two arrays. I want to move one of the elements of the instance element in array1 to the instance in array2.
How can I do it? Which method would you recommend? Does it work to splice the element and push it down? How can a function be written for this? I would be glad if you help.
const array1 = [
{
id: '1',
instance: [
{ id: '34', title: 'Example 1' },
{ id: '35', title: 'Example 2' },
{ id: '36', title: 'Example 3' }, // delete this object from here
},
{
id: '2',
instance: [
{ id: '37', title: 'Example 4' }
],
},
];
I want to move the element I deleted into this array.
const array2 = [
{
id: '1',
instance: [
{ id: '34', title: 'Example 1' },
{ id: '35', title: 'Example 2' },
},
{
id: '2',
instance: [
{ id: '37', title: 'Example 4' },
// { id: '36', title: 'Example 3' }, // i want to move here
],
},
];
You can use pop() to remove last element from array.
const array1 = [{
id: '1',
instance: [{
id: '34',
title: 'Example 1'
},
{
id: '35',
title: 'Example 2'
},
{
id: '36',
title: 'Example 3'
}
],
}, {
id: '2',
instance: [{
id: '37',
title: 'Example 4'
}],
}, ];
let tmp = array1[0].instance[2];
array1[0].instance.pop();
array1[1].instance.push(tmp);
console.log(array1);
const array1 = [
{
id: '1',
instance: [
{ id: '34', title: 'Example 1' },
{ id: '35', title: 'Example 2' },
{ id: '36', title: 'Example 3' }, // delete this object from here
]
},
{
id: '2',
instance: [
{ id: '37', title: 'Example 4' }
]
}
];
const array2 = [
{
id: '1',
instance: [
{ id: '34', title: 'Example 1' },
{ id: '35', title: 'Example 2' },
]
},
{
id: '2',
instance: [
{ id: '37', title: 'Example 4' },
// { id: '36', title: 'Example 3' }, // i want to move here
]
}
];
//answer
function transfer(fromArr,index,toArr){
toArr.push(fromArr.splice(index,1))
}
transfer(array1[0].instance,2,array2[1].instance)
console.log("first array",array1)
console.log("second array",array2)
const array1 = [
{
id: '1',
instance: [
{ id: '34', title: 'Example 1' },
{ id: '35', title: 'Example 2' },
{ id: '36', title: 'Example 3' },] // delete this object from here
},
{
id: '2',
instance: [
{ id: '37', title: 'Example 4' }
],
},
];
var temp = array1[0]
array1.splice(0,1);
const array2 = [
{
id: '1',
instance: [
{ id: '34', title: 'Example 1' },
{ id: '35', title: 'Example 2' },]
},
{
id: '2',
instance: [
{ id: '37', title: 'Example 4' },
// { id: '36', title: 'Example 3' }, // i want to move here
],
},
];
array2.push(temp)
console.log(array2)
First thing, your object has wrong brackets. Here is a fixed version for array1
const array1 = [
{
id: '1',
instance: [
{ id: '34', title: 'Example 1' },
{ id: '35', title: 'Example 2' },
{ id: '36', title: 'Example 3' }, // delete this object from here
]
},
{
id: '2',
instance: [
{ id: '37', title: 'Example 4' }
],
},
];
Now remove one element, IDK how you're getting the key for this, so I ill just declare it as constant, up to you to modify
let key = 0;
let Nested_key = 2;
let removed = array1[key].instance.splice(Nested_key,1) //1st param= 0: the position, 2nd param = 1 number of elements to rm starting from param1 position
Now we removed the element, and it is stored in removed (an array of length=1), just insert it now
array2[key].instance.push(removed[0]);
Judging by your post, it Seems like you knew already what splice and push are and what they do (the name are quite clear and intuitive). Feel free to ask for clarifications if there is any part that you don't understand in my answer

How can I achieve this with Lodash?

I would like to group all messages between 2 people in a group (chat). Doesn`t matter if I am the author or receiver.
Let's say this example code.
const messages = [
{ id: '100', text: 'aaa', author: { id: '1' }, receiver: { id: '2' } },
{ id: '101', text: 'bbb', author: { id: '2' }, receiver: { id: '1' } },
{ id: '102', text: 'ccc', author: { id: '3' }, receiver: { id: '1' } },
]
Imagine, I am user ID = 1, so I would like to get this:
const chats = [
{
chatName: 'Name of user ID 2', messages: [
{ id: '100', text: 'aaa', author: { id: '1' }, receiver: { id: '2' } },
{ id: '101', text: 'bbb', author: { id: '2' }, receiver: { id: '1' } },
]
},
{
chatName: 'Name of user ID 3', messages: [
{ id: '102', text: 'ccc', author: { id: '3' }, receiver: { id: '1' } },
]
}
];
How can I achieve this with Lodash?
Not sure about lodash, but you can use plain js - reduce and map to get that structure
const messages = [{
id: '100',
text: 'aaa',
author: {
id: '1'
},
receiver: {
id: '2'
}
},
{
id: '101',
text: 'bbb',
author: {
id: '2'
},
receiver: {
id: '1'
}
},
{
id: '102',
text: 'ccc',
author: {
id: '3'
},
receiver: {
id: '1'
}
},
];
function groupByPair(arr) {
return [
...arr.reduce((a, b) => {
let {
author,
receiver
} = b;
let s = [author.id, receiver.id].sort().join('-');
a.set(s, a.has(s) ? a.get(s).concat(b) : [b]);
return a;
}, new Map)
].map(e => ({
chatName: 'Name of user ID ' + e[0].substring(e[0].indexOf('-') + 1),
messages: e[1]
}));
}
console.log(groupByPair(messages));
Using either Lodash or Underscore.js:
var grouped = _.groupBy(messages, m => _.sortBy([m.author.id, m.receiver.id]));
var formatted = _.map(grouped, (v, name) => ({ chatname: name, messages: v }));
You could combine those into a single line, but that seems overly dense to my eyes.
I took the liberty of defining a more complex test dataset, to make sure the edge cases were better covered:
var messages = [
{ id: '100', text: 'aaa', author: { id: '1' }, receiver: { id: '2' } },
{ id: '101', text: 'bbb', author: { id: '2' }, receiver: { id: '1' } },
{ id: '102', text: 'ccc', author: { id: '3' }, receiver: { id: '1' } },
{ id: '103', text: 'zzz', author: { id: '2' }, receiver: { id: '1' } },
{ id: '104', text: 'yyy', author: { id: '3' }, receiver: { id: '4' } },
{ id: '105', text: 'xxx', author: { id: '3' }, receiver: { id: '1' } }
]
With this data, the code above yields a formatted of:
[
{ chatname: '1,2',
messages: [
{ id: '100', text: 'aaa', author: { id: '1' }, receiver: { id: '2' } },
{ id: '101', text: 'bbb', author: { id: '2' }, receiver: { id: '1' } },
{ id: '103', text: 'zzz', author: { id: '2' }, receiver: { id: '1' } }
]
},
{ chatname: '1,3', messages: [
{ id: '102', text: 'ccc', author: { id: '3' }, receiver: { id: '1' } },
{ id: '105', text: 'xxx', author: { id: '3' }, receiver: { id: '1' } }
]
},
{ chatname: '3,4', messages: [
{ id: '104', text: 'yyy', author: { id: '3' }, receiver: { id: '4' } }
]
}
]
The major difference with your desired output relates to the chatname values. I did not see how you were naming those, so I stuck with Lodash/Underscore's native groupby keys.
You can do this with _.groupby. I filter the array first so that you're only left with messages that involve user 1.
const messages = [
{ id: '100', text: 'aaa', author: { id: '1' }, receiver: { id: '2' } },
{ id: '101', text: 'bbb', author: { id: '2' }, receiver: { id: '1' } },
{ id: '102', text: 'ccc', author: { id: '3' }, receiver: { id: '1' } },
];
const filtered = messages.filter((msg) => {
return msg.author.id === '1' || msg.receiver.id === '1'
});
const groups = _.groupBy(filtered, (msg) => {
return msg.author.id === '1' ? msg.receiver.id : msg.author.id
});
console.log(groups);
<script src="https://unpkg.com/lodash#4.17.4"></script>

Categories

Resources