I have a structure similar to this (only test data, so typos are irrelevant):
"People" : [
{
"name": "Bob",
"animals" : [{
"name" : "Scott",
"type" : "Cat"
},
{
"name" : "Eva",
"type" : "Cat"
}
{
"name" : "Sven",
"type" : "Dog"
}]
},
{
"name": "Bob",
"animals" : [{
"name" : "Chris",
"type" : "Dog"
},
{
"name" : "Greg",
"type" : "Cat"
},
{
"name" : "Ior",
"type" : "Horse"
}]
}
]
Basically what I want to do is to get all unique animal types from this collection. My problem is mapping into two arrays (People : [], Animals : []). The question:
How do I .map all the "type" attributes to get a new unique collection? like:
["Cat", "Dog", "Horse"]
Will update if I get an example done using C# LINQ.
let _animals = {}
People.forEach(person => {
person.animals.forEach(animal => {
_animals[animal.name] = true
})
})
let result = Object.keys(_animals)
Enhanced with more es6:
let _animals = {}
People.forEach(({animals}) =>
animals.forEach(({name}) =>
_animals[name] = true
)
)
let result = Object.keys(animals)
var unique = {}; // Create an associative array
for (j = 0; j < People.length; j++) { // Iterate through Parents
for(i = 0; i < People[j].animals.length; i++) { // Iterate through animals
var node = unique[People[j].animals[i].type] = unique[People[j].animals[i].type] || {};
// Here unique is built. If there is no entry with the current type as the id, a new entry in unique will be added.
}
}
Use reduce, map, concat and finally to Set to Array as shown below
var output = [...new Set( arr.reduce( (a,c) => a.concat( c.animals.map( s => s.type )) , []))]
Explanation
Use reduce to iterate array (people) to get all values for animals type
Use map to iterate animals and return their types, and concatenate result of map to accumulator a
Use Set to remove duplicates.
Use spread operator ... to convert back to Array.
Demo
var arr = [{
"name": "Bob",
"animals": [{
"name": "Scott",
"type": "Cat"
},
{
"name": "Eva",
"type": "Cat"
},
{
"name": "Sven",
"type": "Dog"
}
]
},
{
"name": "Bob",
"animals": [{
"name": "Chris",
"type": "Dog"
},
{
"name": "Greg",
"type": "Cat"
},
{
"name": "Ior",
"type": "Horse"
}
]
}
];
var output = [...new Set(arr.reduce((a, c) => a.concat(c.animals.map(s => s.type)), []))];
console.log(output);
See Set and Array.prototype.forEach() for more info on animalsFrom().
See Array.prototype.map() and Flattening Arrays for more info on the latter method (listAnimals()).
// Input.
const input = {"people": [{"name": "Bob","animals": [{"name": "Scott","type": "Cat"},{"name" : "Eva","type": "Cat"},{"name" : "Sven","type": "Dog"}]},{"name": "Bob","animals": [{"name" : "Chris","type" : "Dog"},{"name": "Greg","type": "Cat"},{"name": "Ior","type": "Horse"}]}]}
// Animals From.
const animalsFrom = ({people}) => {
const animals = new Set()
people.forEach(person => {
person.animals.forEach(animal => animals.add(animal.type))
})
return [...animals.values()]
}
// List Animals (Advanced).
const listAnimals = ({people}) => [...new Set([].concat.apply([], people.map(({animals}) => animals.map(({type}) => type))))]
// Proof.
console.log('Animals From', animalsFrom(input))
console.log('List Animals', listAnimals(input))
ES6
You can use reduce(), new Set([]) and the spread operator to get the required result.
DEMO
const arr = [{
"name": "Bob",
"animals": [{
"name": "Scott",
"type": "Cat"
}, {
"name": "Eva",
"type": "Cat"
}, {
"name": "Sven",
"type": "Dog"
}]
}, {
"name": "Bob",
"animals": [{
"name": "Chris",
"type": "Dog"
}, {
"name": "Greg",
"type": "Cat"
}, {
"name": "Ior",
"type": "Horse"
}]
}];
let result = arr.reduce((r, {animals}) =>[...r,...animals.map(({type})=>type)], []);
console.log([ ...new Set(result)]);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Related
This array has the key to substitute with nested key of 'name'
const arr = ['status', 'user', ...] <-- This array contains key to be replaced with name
This is what my current response object is
[
{
"id": 11,
"location": "Mumbai",
"status": {
"name": "NEW"
},
"user": {
"name": "Rakesh"
}
}
]
How do I modify the above array of objects to this below
[
{
"id": 11,
"location": "Mumbai",
"status": "NEW",
"user": "Rakesh"
}
]
can try below code
const keys = ['status', 'user']
let arr = [
{
"id": 11,
"location": "Mumbai",
"status": {
"name": "NEW"
},
"user": {
"name": "Rakesh"
}
}
]
arr.map(a => keys.forEach(k => {
if(a[k] && a[k].name) a[k] = a[k].name
}));
console.log(arr);
I'd try this one:
const results = [
{
"id": 11,
"location": "Mumbai",
"status": {
"name": "NEW"
},
"user": {
"name": "Rakesh"
}
}, {
"id": 12,
"location": "Helsinki",
"status": {
"name": "NEW"
},
"user": {
"name": "Samuli"
}
}
];
const flattenObject = ([key, value]) => ((typeof value === 'object') ? {[key] : value[Object.keys(value)[0]]} : {[key]: value});
const reduceToSingleObject = (acc, b) => ({...acc, ...b});
const actualResults = results.map((result) => Object.entries(result).map(flattenObject).reduce(reduceToSingleObject));
console.log(actualResults);
Explanation:
flattenObject is a function to flatten structure of object inside object. This only takes the first prop (without knowing the name of the key). If you, for some reason, would need to flatten several key-values, then it'd need whole different kind of helper function to sort that out.
reduceToSingleObject is a function to put all the key-value pairs into a single object. This could have been done already in flattenObject function, but for the clarity, I separated it to a normal map - reduce pattern.
actualResults is the outcome where we go through all the entries of your original results.
I'm trying to filter everything inside 'items' with 'name': "", without losing structure and values of fieldLabel and placeholder. Below is my current object:
result: {
"fieldLabel": "foo",
"placeholder": "foo",
"items": [
{
"name": "foobar"
},
"name": ""
},
{
"name": ""
}
]
}
I want the object to look like this after filtering:
result: {
"fieldLabel": "foo",
"placeholder": "foo",
"items": [
{
"name": "foobar"
},
]
}
Have a reference to the original object first.
const results = {
"fieldLabel": "foo",
"placeholder": "foo",
"items": [
{
"name": "foobar"
},
{
"name": ""
},
{
"name": ""
}
]
}
Create a new object from the reference. Use spread syntax for copying object. Then filter method for filtering
const newObject = {
...results,
items: results.items.filter(item => item.name)
}
You can filter the nested items array that have truthy name properties.
const result= {
"fieldLabel": "foo",
"placeholder": "foo",
"items": [
{
"name": "foobar"
},
{
"name": ""
},
{
"name": ""
}
]
};
result.items = result.items.filter(({ name }) => name);
console.log(result);
If you need to do this using an immutable pattern then shallow copy the object and nested properties that you are updating.
const result= {
"fieldLabel": "foo",
"placeholder": "foo",
"items": [
{
"name": "foobar"
},
{
"name": ""
},
{
"name": ""
}
]
};
const newresult = {
...result,
items: result.items.filter(({ name }) => name)
};
console.log(newresult);
console.log(result === newresult); // false since new object
Something like this?
Filter YOUROBJ.items to keep all entries where property name has a value that is not null/undefined/false
res.items = res.items.filter(e => e.name);
const obj = {
"fieldLabel": "foo",
"placeholder": "foo",
"items": [
{
"name": "foobar"
},
{
"name": ""
},
{
"name": ""
}
]
}
const res = Object.assign({}, obj); // copy object to not mutate the original one
res.items = res.items.filter(e => e.name); // filter array "items" to just keep items with property name
console.log(res);
I need to iterate a nested value in my javascript.
My wanted output should be like this
shows: ['food.order', 'drink.order', 'play.basketball', 'play.soccer']
const results = [
{
"ID": "shops",
"Shopping": [
{
"ID": "food.order",
"Name": "Food"
},
{
"ID": "drink.order",
"Name": "Drink"
}
]
},
{
"ID": "fun",
"Sports": [
{
"ID": "play.basketball",
"Name": "Basketball"
},
{
"ID": "play.soccer",
"Name": "Soccer"
},
]
}
];
console.log(results);
const final = { shows: results.map(data => data['key'].ID) }
Your question is not clear though, but I am assuming that you are searching for ID property and want to grab the value of the ID and make an array. You can try this way-
const results = [{"ID": "shops", "Shopping": [{ "ID": "food.order", "Name": "Food"},{ "ID": "drink.order", "Name": "Drink"}]},{"ID": "fun", "Sports": [{ "ID": "play.basketball", "Name": "Basketball"},{ "ID": "play.soccer", "Name": "Soccer"}]}];
const ans = results.reduce((acc, item) => {
// Iterate throw the each item's properties
Object.values(item).forEach(val => {
// Filter out the objects which has the `ID` property and get the value of the `ID`.
const ids = typeof val === 'object' && val instanceof Array
? val.filter(x => x.ID !== undefined).map(({ID}) => ID)
: [];
acc = [...acc, ...ids];
});
return acc;
}, []);
console.log(ans);
.as-console-wrapper {min-height: 100%!important; top: 0}
Are you looking for something like this?
const results = [{"ID": "shops", "Shopping": [{ "ID": "food.order", "Name": "Food"},{ "ID": "drink.order", "Name": "Drink"}]},{"ID": "fun", "Sports": [{ "ID": "play.basketball", "Name": "Basketball"},{ "ID": "play.soccer", "Name": "Soccer"}]}];
const final = results.reduce((p, n) => {
// Get all object's array props and then reduce their keys
const mapped = Object.keys(n).filter((key) => Array.isArray(n[key])).reduce((arr, key) => [
...arr,
// Get the array by using the object's key, filter out all objects which don't have
// an 'ID' key, and return a new array which only contains the x.ID property
...n[key].filter((x) => x.ID).map((x) => x.ID)
], []);
return [
...p,
...mapped,
];
}, []);
console.log('final', final);
const results=[{ID:"shops",Shopping:[{ID:"food.order",Name:"Food"},{ID:"drink.order",Name:"Drink"}]},{ID:"fun",Sports:[{ID:"play.basketball",Name:"Basketball"},{ID:"play.soccer",Name:"Soccer"}]}];
let arr = results.flatMap(e => Object.values(e).filter(n => Array.isArray(n))) // at this stage you have an array of arrays
.flat() // at this stage you have flat array from previous stage
.map(s => s.ID) // Now you pick the IDs
console.log(arr)
How can I convert this object:
var json = {
"user3" : {
"id" : 1
},
"user1" : {
"id" : 3
},
"user2" : {
"id" : 6
}
}
to this array:
var json = [{
"name": "user1",
"id": 3
}, {
"name": "user2",
"id": 6
}, {
"name": "user3",
"id": 1
}];
Can someone tell me? Or how can I sort an object like the first example?
Try
const src = {
"user3" : {
"id" : 1
},
"user1" : {
"id" : 3
},
"user2" : {
"id" : 6
}
}
const out = Object.keys(src).map((key) => ({name: key, id: src[key].id}))
You can use Object.keys() and Array.prototype.reduce() to iterate over the object items and create an array out of the single items.
Object.keys(json).reduce((items, username) => {
const user = json[username];
return items.concat({
name: username,
id: user.id
});
}, []);
You can use Object.entries to convert the object into an array. Use map to loop thru the array and use Object.assign to construct the new object.
var json = {
"user3": {
"id": 1
},
"user1": {
"id": 3
},
"user2": {
"id": 6
}
}
var result = Object.entries(json).map(([k, o]) =>Object.assign(o, {name: k}));
console.log(result);
An alternative approach, using a for-in loop:
const json = {
"user3": {
"id": 1
},
"user1": {
"id": 3
},
"user2": {
"id": 6
}
}
const result = [];
for (const prop in json) {
result.push({ "name": prop, "id": json[prop].id });
}
console.log(result);
Will provide:
[ { name: 'user3', id: 1 },
{ name: 'user1', id: 3 },
{ name: 'user2', id: 6 } ]
How to filter objects in array based on unique property
here i have an array where KEY is the key value in the objects.
How to filter the objects where key value is unique. Key value is repeated in the objects but should only the first one should be filtered out.
var array = [];
array = [
{
"KEY": "00001",
"ID": "1234",
"ID_DESC": "1234",
"NOT_UNIQUE_VALUE": "119.0",
"NOT_UNIQUE_TYPE": "this is not unique"
},
{
"KEY":"00001",
"ID":"1234",
"ID_DESC":"1234",
"NOT_UNIQUE_VALUE":"11019.0",
"NOT_UNIQUE_TYPE":"not unique type"
},
{
"KEY":"00002",
"ID":"2468",
"ID_DESC":"2468",
"NOT_UNIQUE_VALUE":"195.0",
"NOT_UNIQUE_TYPE":"not unique type",
},
{
"KEY":"00002",
"ID":"2468",
"ID_DESC":"2468",
"NOT_UNIQUE_VALUE":"195.0",
"NOT_UNIQUE_TYPE":"not unique type",
}]
Result:
uniquearray = [
{
"KEY":"00001",
"ID":"1234",
"ID_DESC":"1234",
"NOT_UNIQUE_VALUE":"119.0",
"NO T_UNIQUE_TYPE":"this is not unique"
},
{
"KEY":"00002",
"ID":"2468",
"ID_DESC":"2468",
"NOT_UNIQUE_VALUE":"195.0",
"NOT_UNIQUE_TYPE":"not unique type"
}]
You can iterate over the members and look at the KEY property. If it's not been seen before, add it to a list of seen keys and return true. If it has been seen before, return false. E.g.
var array = [{
"KEY": "00001",
"ID": "1234",
"ID_DESC": "1234",
"NOT_UNIQUE_VALUE": "119.0",
"NOT_UNIQUE_TYPE": "this is not unique"
}, {
"KEY": "00001",
"ID": "1234",
"ID_DESC": "1234",
"NOT_UNIQUE_VALUE": "11019.0",
"NOT_UNIQUE_TYPE": "not unique type"
}, {
"KEY": "00002",
"ID": "2468",
"ID_DESC": "2468",
"NOT_UNIQUE_VALUE": "195.0",
"NOT_UNIQUE_TYPE": "not unique type",
}, {
"KEY": "00002",
"ID": "2468",
"ID_DESC": "2468",
"NOT_UNIQUE_VALUE": "195.0",
"NOT_UNIQUE_TYPE": "not unique type",
}]
var seenKeys = Object.create(null);
var result = array.filter(function(obj) {
return seenKeys[obj.KEY]? false : seenKeys[obj.KEY] = true;
});
console.log(result)
As an arrow function:
var seenKeys = Object.create(null);
var result = array.filter(obj => seenKeys[obj.KEY]? false : seenKeys[obj.KEY] = true);
I would go with reduce(), collecting unique elements into a Map (it even preserves insertion order, if that is expected), and packing it back to an array at the end:
var array = [{
"KEY": "00001",
"ID": "1234",
"ID_DESC": "1234",
"NOT_UNIQUE_VALUE": "119.0",
"NOT_UNIQUE_TYPE": "this is not unique"
}, {
"KEY": "00001",
"ID": "1234",
"ID_DESC": "1234",
"NOT_UNIQUE_VALUE": "11019.0",
"NOT_UNIQUE_TYPE": "not unique type"
}, {
"KEY": "00002",
"ID": "2468",
"ID_DESC": "2468",
"NOT_UNIQUE_VALUE": "195.0",
"NOT_UNIQUE_TYPE": "not unique type",
}, {
"KEY": "00002",
"ID": "2468",
"ID_DESC": "2468",
"NOT_UNIQUE_VALUE": "195.0",
"NOT_UNIQUE_TYPE": "not unique type",
}]
var result = Array.from(array.reduce((m,o) => {
if(!m.has(o.KEY))
m.set(o.KEY, o);
return m;
}, new Map()).values());
console.log(result)
Here is a ES6 version filter utility:
// Unique is only that item, if we find him in array on the same index.
const onlyUniqueProperty = prop => (value, index, self) =>
self.findIndex(item => item[prop] === value[prop]) === index;
// Usage:
const uniqueItems = items.filter(onlyUniqueProperty('key'));
If we want to support both JS and Immutable.js objects, small update:
const getProp = (obj, prop) => typeof obj.get === 'function' ? obj.get(prop) : obj[prop];
// Unique is only that item, if we find him in array on the same index.
const onlyUniqueProperty = prop => (value, index, self) =>
self.findIndex(item => getProp(item, prop) === getProp(value, prop)) === index;
// Usage:
const uniqueItems = items.filter(onlyUniqueProperty('key'));
var uniqueArray = []
for (var i = 0; i < array.length; i++) {
var uniquevalue = array[i];
unique[array.KEY] = uniquevalue;
}
for (var name in unique) {
var uniqueObject = unique[name];
uniqueArray.push(uniqueObject);
}