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)
Related
Javascript
I have a nested array of objects, I'm trying to filter the given array of objects using a property from the third level of its array property value. For example, from the below array I like to filter the entire array using the property ListId: 10
Example
let test = {
"test":true,
"group":[
{
"name":"header",
"value":[
{
"id":"0",
"list":[
{
"ListId":10,
"name":"string1",
"state":"BY",
"techId":0
},
{
"ListId":11,
"name":"string2",
"state":"BY"
},
{
"ListId":12,
"name":"string3",
"state":"BY"
}
]
}
]
},
{
"name":"header2",
"value":[
{
"id":"01",
"list":[
{
"ListId":100,
"name":"string1",
"state":"BY",
"techId":0
},
{
"ListId":111,
"name":"string2",
"state":"BY"
},
{
"ListId":121,
"name":"string3",
"state":"BY"
}
]
}
]
}
]
}
Filtervalue with ListId = 10
Expected output :
{
"test":true,
"group":[
{
"name":"header",
"value":[
{
"id":"0",
"list":[
{
"ListId":10,
"name":"string1",
"state":"BY",
"techId":0
}
]
}
]
}
]
}
How can I use the filter method using javascript to get this expected result?
You can two it in two times :
First, filter the list arrays,
Secondly filter the groups array using the some method
let test= {
"test": true,
"group": [
{
"name": "header",
"value": [
{
"id": "0",
"list": [
{
"ListId": 10,
"name": "string1",
"state": "BY",
"techId": 0
},
{
"ListId": 11,
"name": "string2",
"state": "BY"
},
{
"ListId": 12,
"name": "string3",
"state": "BY"
}
]
}
]
},
{
"name": "header2",
"value": [
{
"id": "01",
"list": [
{
"ListId": 100,
"name": "string1",
"state": "BY",
"techId": 0
},
{
"ListId": 111,
"name": "string2",
"state": "BY"
},
{
"ListId": 121,
"name": "string3",
"state": "BY"
}
]
}
]
}
]
}
test.group.forEach(group => {
group.value.forEach(value => {
value.list = value.list.filter(list => list.ListId === 10)
})
})
test.group = test.group.filter(group => group.value.some(value => value.list.length > 0))
console.log(test)
Note : You should use plural names for you arrays, it helps understanding the data. For example lists not list for the array.
let z ={"group1": [
{
"name": "header",
"value": [
{
"id": 0,
"list": [
{
"ListId": 10,
"Name": "string1"
},
{
"ListId": 11,
"Name": "string2"
}
]
}
]
}
]}
// This function was written from understading that 'group1' is not a fixed property, but part of a dynamic list due to the number '1'
const getItemByListId = (list, listId) => {
const listKeys = Object.keys(list);
const selectedListKey = listKeys.find(key => {
const groupItems = list[key];
const selectedItem = groupItems.find(({ value: nestedItems }) => {
const selectedNestedItem = nestedItems.find(({ list }) => {
const selectedList = list.find(({ ListId }) => ListId === listId)
return selectedList;
});
return selectedNestedItem;
});
return selectedItem;
});
if (!selectedListKey) {
return null;
}
return list[selectedListKey];
};
console.log(getItemByListId(z, 10));
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);
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);
I have the following array
[ { "id": 1, "name": "Test" }, { "id": 2, "name": "Test2" }
How can I convert that to
[ { "id": '1', "name": "Test" }, { "id": '2', "name": "Test2" }
For all the objects in an array, you want to convert a property type from number to string. You can use Array.forEach to achieve the same.
let arr = [ { "id": 1, "name": "Test" }, { "id": 2, "name": "Test2" }];
arr.forEach(v => v.id += '');
console.log(arr);
So i have an array which stores hobbies for each user in an array within the object..
var hobbies = [
{
"id": 1,
"hobbies": []
},
{
"id": 2,
"hobbies": [
"football"
]
},
{
"id": 3,
"hobbies": [
"football",
"basketball"
]
}
]
What i want to return is a new array of objects but each hobby separated into their own object like below.
var result = [
{
"id": 2,
"hobby": "football"
},
{
"id": 3,
"hobby": "football"
},
{
"id": 3,
"hobby": "basketball"
}
]
What is have so far is
hobbies.filter((f, i) => f.hobbies.length > 0).map((p, i) => {
while (i < p.hobbies.length) {
return { id : p.id, hobby : p.hobbies[i] };
}
});
which only returns
[
{
"id": 2,
"hobby": "football"
},
{
"id": 3,
"hobby": "basketball"
}
]
You can use array#reduce with array#map. Iterate through each object and then iterate through each hobby of hobbies and create the object.
var hobbies = [ { "id": 1, "hobbies": [] }, { "id": 2, "hobbies": [ "football" ] }, { "id": 3, "hobbies": [ "football", "basketball" ] } ],
result = hobbies.reduce((r, {id, hobbies}) => r.concat(hobbies.map(hobby => ({id, hobby}))), []);
console.log(result);
I know, "functional" programming is considered "cool" around these parts, however, have you considered using simple loops to, well, loop over your data?
let result = [];
for (let {hobbies, id} of data)
for (let hobby of hobbies)
result.push({id, hobby})
In my opinion, this is far more readable than any reduce spaghetti one could come up with ;)
You need to use inner-loop to loop through the hobbies and push them one-by-one to the target array:
var hobbies = [{
"id": 1,
"hobbies": []
},
{
"id": 2,
"hobbies": [
"football"
]
},
{
"id": 3,
"hobbies": [
"football",
"basketball"
]
}
];
var result = hobbies.reduce((acc, item) => {
item.hobbies.forEach(hobby => {
acc.push({
id: item.id,
hobby: hobby
});
});
return acc;
}, []);
console.log(result);
You can use array.prototype.reduce:
var hobbies = [{"id": 1,"hobbies": []},{"id": 2,"hobbies": ["football"]},{"id": 3, "hobbies": ["football","basketball"]}];
var res = hobbies.reduce((m, o) => (o.hobbies.forEach(h => m.push({id: o.id, hobby: h})), m), []);
console.log(res);
You need nested loops and this is the basics of it:
You first need to loop over the main hobbies array.
Then for each item in the array (which represents a person), you want to loop through their hobbies, and for each one of those hobbies, you need to push an object made up of the profile ID and the hobby into results array I created earlier.
var hobbies = [{ "id": 1, "hobbies": [] }, { "id": 2, "hobbies": [ "football" ] }, { "id": 3, "hobbies": [ "football", "basketball" ] } ];
let result = [];
hobbies.forEach(function(profile){
profile.hobbies.forEach(function(hobby){
result.push(
{
"id": profile.id,
"hobby": hobby
}
);
});
});
console.log(result)
Update: the other answers with Array.reduce (a more specialised loop) will cut the above code down even further.