Combine and flatten elements of array - javascript

With the below JSON content that is actually coming from an API but I'm using a json file for testing. I would like to combine the primary key and flatten the ItemList.
[{
"PrimaryKey": "123",
"ItemList": [
{
"SecondaryKey": "ABC",
"Name": "Item1",
"Description": "Sample item"
},
{
"SecondaryKey": "DEF",
"Name": "Item2",
"Description": "Another sample item"
}
],
"IgnoreThis": [
{
"SomeData": "Some Data"
}
]
}]
The output I would like is:
[{
"PrimaryKey": 123,
"SecondaryKey": "ABC",
"Name": "Item1",
"Description": "Sample Item"
},
{
"PrimaryKey": 123,
"SecondaryKey": "DEF",
"Name": "Item2",
"Description": "Another sample item"
}]
I've got the Item list being flattened by:
let items = [];
items.push(JSON.parse(fs.readFileSync('./items.json')));
let result = items.reduce((r, obj) => r.concat(obj.ItemList), []);
I've tried to use items.map to get the desired output nothing has worked, I don't think I understand how to chain .map and .reduce effectively as I get undefined as the result.
Any ideas how I can achieve this output?

You can do this by running map twice: get the PrimaryKey from the first map, then add it to all the objects inside the second map, then you flatten the array you got from the previous stage.
const data = [
{
PrimaryKey: "123",
ItemList: [
{
SecondaryKey: "ABC",
Name: "Item1",
Description: "Sample item",
},
{
SecondaryKey: "DEF",
Name: "Item2",
Description: "Another sample item",
},
],
IgnoreThis: [
{
SomeData: "Some Data",
},
],
},
{
PrimaryKey: "456",
ItemList: [
{
SecondaryKey: "ABC",
Name: "Item1",
Description: "Sample item",
},
{
SecondaryKey: "DEF",
Name: "Item2",
Description: "Another sample item",
},
],
IgnoreThis: [
{
SomeData: "Some Data",
},
],
},
];
const result = data.map(({ PrimaryKey, ItemList }) => ItemList.map(item => ({
PrimaryKey,
...item,
}))).flat();
console.log(result);

Related

JSON data, need modifications

I have a problem with converting Json data , I get a list objects with different categories for each category there are two versions , So I need to modify the in a way to get list of objects where each object key is the category and its value is list of its corresponding versions and details.
data = [
{
"category1": {
"name": "category1",
"id": 1,
"last_sync_date": "None",
"version": "Version 1"
}
},
{
"category1": {
"name": "category1",
"id": 2,
"last_sync_date": "None",
"version": "Version 2"
}
},
{
"category2": {
"name": "category2",
"id": 1,
"last_sync_date": "None",
"version": "Version 1"
}
},
{
"category3": {
"name": "category3",
"id": 2,
"last_sync_date": "None",
"version": "Version 2"
}
},
]
To:
data = {
category1: [
{
id: "1",
name: "category1",
last_sync_date: "01/01/2022 10:45 AM",
version: "Version 1"
},
{
id: "2",
name: "category1",
last_sync_date: "01/01/2022 10:45 AM",
version: "Version 2"
},
],
category2:[
{
id: "3",
name: "category2",
last_sync_date: "01/01/2022 10:45 AM",
version: "Version 1"
},
],
category3:[
{
id: "4",
name: "category3",
last_sync_date: "01/01/2022 10:45 AM",
version: "Version 1"
},
],
}
Note: I was able to provide only one unit of data.
This is not JSON btw, this is just a JavaScript Array of objects that needs to be converted into another structure.
This can be done with any of the loop logics. I can show you one example with Array.reduce
Logic
Loop through data array using Array.reduce
Take each object and get the keys of each object.
Check whether this key exist in out accumulator object
If the key exist, push the Object to existing key, else create an empty array as the value for that key and push our object to the emty array just created.
const data = [
{
category1: { name: "category1", id: 1, last_sync_date: "None", version: "Version 1" },
},
{
category1: { name: "category1", id: 2, last_sync_date: "None", version: "Version 2" },
},
{
category2: { name: "category2", id: 1, last_sync_date: "None", version: "Version 1" },
},
{
category3: { name: "category3", id: 2, last_sync_date: "None", version: "Version 2" },
},
];
const output = data.reduce((acc, curr) => {
const keys = Object.keys(curr);
keys.forEach((key) => {
acc[key] = acc[key] || [];
acc[key].push(curr[key]);
});
return acc;
}, {});
console.log(output);
The following uses Array#reduce to enumerate the data. It pulls out the category and the object associated with each item. The objects are then added to a result object, keyed by category and grouped within arrays.
Does this do what you want?
const data = [{
"category1": {
"name": "category1",
"id": 1,
"last_sync_date": "None",
"version": "Version 1"
}
}, {
"category1": {
"name": "category1",
"id": 2,
"last_sync_date": "None",
"version": "Version 2"
}
}, {
"category2": {
"name": "category2",
"id": 1,
"last_sync_date": "None",
"version": "Version 1"
}
}, {
"category3": {
"name": "category3",
"id": 2,
"last_sync_date": "None",
"version": "Version 1"
}
}, ]
const group = (data) =>
data.reduce((acc, c) => {
const [[category, value]] = Object.entries(c)
acc[category]
? acc[category].push(value)
: acc[category] = [value]
return acc
}, {})
console.log(group(data))
This is not a JSON structure. Input is an array of objects. According to your description you just want to convert it to another structure.
Here is a sample solution of this problem.
// const data = [{}, {}...]; Input array of objects
const ans = {};
data.map(object => {
const keys = Object.keys(object);// to get keys of current object
const firstKey = keys[0];
const value = object[firstKey];
if (ans[firstKey] == undefined) {
ans[firstKey] = [value];
} else {
ans[firstKey].push(value);
}
})
console.log(ans);

create a new array from the keys of an Array's Object

I have a array of objects, and by using the foreach or map I want to create new array from its keys:
[{
"name": "Dentist Specialist",
"category": "Roles",
"path": "cde"
},
{
"name": "Root Canal Therapy",
"category": "Procedures",
"path": "abc"
},
{
"name": "Live Course",
"category": "Course Type",
"path": "mfg"
}]
From the above array I need a new ARRAY which will look like this:
[{
"Roles": "Dentist Specialist"
},
{
"Procedures": "Root Canal Therapy"
},
{
"Course Type": "Live Course"
}]
Just replace the 2nd key with the first key and remove the rest.
You can use map here to achieve the desired result.
arr.map(({ category, name }) => ({ [category]: name }));
or
arr.map((o) => ({ [o.category]: o.name }));
const arr = [
{
name: "Dentist Specialist",
category: "Roles",
path: "cde",
},
{
name: "Root Canal Therapy",
category: "Procedures",
path: "abc",
},
{
name: "Live Course",
category: "Course Type",
path: "mfg",
},
];
const result = arr.map((o) => ({ [o.category]: o.name }));
console.log(result);

Return name and id property value of all arrays inside object

How to return name and id property value of all arrays? The idea is to make a single map of all these arrays and return the id and name?
Something like this
filters.[key].map((option, index) => (
<ItemFilter key={index}>{option}</ItemFilter>
))
I have this array object
filters: {
"services": [
{
"id": "1b975589-7111-46a4-b433-d0e3c0d7c08c",
"name": "Bank"
},
{
"id": "91d4637e-a17f-4b31-8675-c041fe06e2ad",
"name": "Income"
}
],
"accountTypes": [
{
"id": "1f34205b-2e5a-430e-982c-5673cbdb3a68",
"name": "Digital Account"
}
],
"channels": [
{
"id": "875f8350-073e-4a20-be20-38482a86892b",
"name": "Chat"
}
]
}
You can use flatMap or flat to achieve the desired result.
Object.values(obj.filters).flatMap(v => v)
or
Object.values(obj.filters).flat()
const obj = {
filters: {
services: [
{
id: "1b975589-7111-46a4-b433-d0e3c0d7c08c",
name: "Bank",
},
{
id: "91d4637e-a17f-4b31-8675-c041fe06e2ad",
name: "Income",
},
],
accountTypes: [
{
id: "1f34205b-2e5a-430e-982c-5673cbdb3a68",
name: "Digital Account",
},
],
channels: [
{
id: "875f8350-073e-4a20-be20-38482a86892b",
name: "Chat",
},
],
},
};
const result = Object.values(obj.filters).flatMap(v => v);
console.log(result);
If option is referring to name in your example code it could look something like this:
Object.values(
{
filters: {
services: [
{
id: "1b975589-7111-46a4-b433-d0e3c0d7c08c",
name: "Bank",
},
{
id: "91d4637e-a17f-4b31-8675-c041fe06e2ad",
name: "Income",
},
],
accountTypes: [
{
id: "1f34205b-2e5a-430e-982c-5673cbdb3a68",
name: "Digital Account",
},
],
channels: [
{
id: "875f8350-073e-4a20-be20-38482a86892b",
name: "Chat",
},
],
},
}.filters
)
.flat()
.map(({ name, index }) => <ItemFilter key={index}>{name}</ItemFilter>);

how to get array from object with index as one of the object property

I have an object
const items = {
"123": {
"key": 123,
"name": "one name",
},
"456": {
"key": 456,
"name": "two name",
},
"789": {
"key": 789,
"name": "three name",
},
};
Need to filter this from below array, with array index as object.key
const myFilter = [123,789];
Code I am trying is as below but it returning array inedx as 0,1,2... but I need the index to be object.key.
let selectedItems = myFilter.map((key) => {
return items[key];
});
Current output :
[0:{
key: 123,
name: "one name"
}, 1: {
key: 789,
name: "three name"
}]
Expected Output
[123:{
key: 123,
name: "one name"
}, 789: {
key: 789,
name: "three name"
}]
jsfiddle - https://jsfiddle.net/kb374exh/2/
Your actual output is actually correct and the only possible result from mapping the myFilter array to the matching properties from items.
const items = {
"123": {
"key": 123,
"name": "one name",
},
"456": {
"key": 456,
"name": "two name",
},
"789": {
"key": 789,
"name": "three name",
},
};
const myFilter = [123, 789];
const selectedItems = myFilter.map((key) => items[key]);
console.log(selectedItems);
The logged output you see is including the array index. You likely are seeing the index included when logging in the browser.
If you want an array of objects where the original key is the new index then the best you can likely do is an array of length <highest key> and a bunch of "holes" that are simply undefined.
const items = {
"123": {
"key": 123,
"name": "one name",
},
"456": {
"key": 456,
"name": "two name",
},
"789": {
"key": 789,
"name": "three name",
},
};
const myFilter = [123, 789];
const selectedItems = Object.entries(items).reduce((selectedItems, [key, value]) => {
if (myFilter.includes(value.key)) selectedItems[key] = value;
return selectedItems;
}, []);
console.log(selectedItems);
If you are ok with the result being an object then you can have more succinct output, you'll basically end up with back with an object with key-value pairs filtered out.
const items = {
"123": {
"key": 123,
"name": "one name",
},
"456": {
"key": 456,
"name": "two name",
},
"789": {
"key": 789,
"name": "three name",
},
};
const myFilter = [123, 789];
const selectedItems = Object.fromEntries(Object.entries(items).filter(([, value]) => myFilter.includes(value.key)));
console.log(selectedItems);

Removing nested arrays

I have an array that contains a lot of base attributes and multiple nested arrays. I'm trying to remove the nested arrays leaving all the base items. I don't want to filter them out by name but type.
{
"ID": 123,
"ItemName": "Item1",
"CommentList": [
{
"CommentID": "ABC",
"CommentText": "Test entry"
}
],
"ExtraList": [
"A123B"
]
}
The desired outcome is:
{
"ID": 123,
"ItemName": "Item1",
}
I tried filter but couldnt get it to work, the below is the closest I've come but given the fact I can't gracefully return the property back to the caller this must be the wrong track.
let test = arr.forEach(function (item) {
for (var propertyName in item) {
if (!Array.isArray(propertyName))
return propertyName;
}
});
For starters, Array.prototype.forEach does not return a new array. Please use Array.prototype.map instead if you would like to return a new array.
I am only saying this because you are assigning it to test, which would return undefined.
With that out of they way this should work
data.forEach(item => {
for(const key in item) {
if(Array.isArray(item[key])) {
delete item[key]
}
}
})
Here is the code that input and output:
Input:
const data = [
{
"ID": 123,
"ItemName": "Item1",
"CommentList": [
{
"CommentID": "ABC",
"CommentText": "Test entry"
}
],
"ExtraList": [
"A123B"
]
},
{
"ID": 124,
"ItemName": "Item1",
"CommentList": [
{
"CommentID": "ABC",
"CommentText": "Test entry"
}
],
"ExtraList": [
"A123B"
]
}
]
Output:
[
{ID: 123, ItemName: "Item1"},
{ID: 124, ItemName: "Item1"}
]
Hope this helps!
Try this
const a = {
"ID": 123,
"ItemName": "Item1",
"CommentList": [
{
"CommentID": "ABC",
"CommentText": "Test entry"
}
],
"ExtraList": [
"A123B"
]
}
const obj = {};
Object.keys(a)
.filter(key => !(a[key] instanceof Array))
.forEach(key => obj[key] = a[key]);
console.log(obj);
arr is an object, you can get an arrays of keys with Object.keys(obj) an then filter it.
let obj = {
"ID": 123,
"ItemName": "Item1",
"CommentList": [{
"CommentID": "ABC",
"CommentText": "Test entry"
}],
"ExtraList": [
"A123B"
]
}
let test = Object.keys(obj).filter((key) => {
return !Array.isArray(obj[key])
})
console.log(test)
You can Do this way, The easiest way to Do this
const data = [
{
"ID": 123,
"ItemName": "Item1",
"CommentList": [
{
"CommentID": "ABC",
"CommentText": "Test entry"
}
],
"ExtraList": [
"A123B"
]
},
{
"ID": 124,
"ItemName": "Item2",
"CommentList": [
{
"CommentID": "CDE",
"CommentText": "Test entry 2"
}
],
"ExtraList": [
"A123BC"
]
}
]
let finalOutput=JSON.parse(JSON.stringify(data,['ID','ItemName']))
console.log(finalOutput)

Categories