There's about million questions (and answers) out there on this topic, but none of them are doing what I need to do. I have a JSON object where the value for each key is an object. I want to convert this to an array and maintain the top level keys.
{
"someKey1": {
active: true,
name: "foo"
},
"someKey2": {
active: false,
name: "bar"
}
}
If I use Object.keys() I get the top level keys, but not their values. If I use Object.values() I get an array with all the values, but not their keys. I'm trying to use keys and map, but am only getting the values returned:
const data = {
"someKey1": {
active: true,
name: "foo"
},
"someKey2": {
active: false,
name: "bar"
}
}
const items = Object.keys(data).map(function(key) {
return data[key];
});
// returns [{active: true, name: foo},{active: false, name: bar}]
Is there a way to get both? I want to get an array I can iterate over that looks something like this:
[{
key: someKey1,
active: true,
name: "foo"
},
{
key: someKey2,
active: true,
name: "foo"
}]
OR
[
"someKey1": {
active: true,
name: "foo"
},
"someKey2": {
active: false,
name: "bar"
}
]
I think you are going in the right direction, if you want to add the "key" property you have to map the properties manually and for the second option since you don't need the "key" property it can be done a little bit more elegantly:
For the first option:
Object.keys(data).map(v => ({
key: v,
...data[v]
}));
For the second option even simpler:
Object.keys(data).map(v => ({[v]: {...data[v]}}))
You can easily map your data to a new object:
Object.keys(data).map(key => ({ ...data[key], "key": key }));
My task is to filter objects by values in nested arrays. like in example below:
const array = [
{
authorId: '62222a1cea00a0601f200142',
description: [
[
{
title: 'English description',
paragraph: 'And english paragraph!!!!',
},
],
[
{
title: 'some title!!!',
paragraph: 'some para!!',
},
],
],
removed: false,
status: 'NEW',
},
{
authorId: '621f97562511255efa0f135e',
description: [
[
{
title: 'EEEE',
paragraph: 'aaaa',
},
],
],
removed: false,
status: 'NEW',
},
{
description: [
[
{
title: 'TEST',
paragraph: 'TESR',
},
],
],
removed: false,
status: 'NEW',
},
{
authorId: '621f97432511255efa0f135c',
description: [
[
{
title: 'My task',
paragraph: 'Parapgraph 19',
},
],
],
removed: false,
status: 'NEW',
},
]
my expected results is something like that, based on search input, which is conts searchInput
const searchInput = "par"
const array = [
{
authorId: '62222a1200142',
description: [
[
{
title: 'English description',
paragraph: 'And english paragraph!!!!',
},
],
[
{
title: 'some title!!!',
paragraph: 'some para!!',
},
],
],
removed: false,
status: 'NEW',
},
{
authorId: '6a000142',
description: [
[
{
title: 'TEST',
paragraph: 'paragraph one',
},
],
],
removed: false,
status: 'NEW',
},
]
Ive already try something like this:
const results = array?.map((el) => el?.description.map((i) => i.map((item) => item.paragraph))).filter((description) =>description.toString().toLowerCase().includes(searchValue))
But it return only arrays with paragraphs and i expected to filter whole objects, with all data, not only strings
You need to put the map inside the filter, so your data isn't modified. You use first map the description paragraphs into an array and check if all the values of the paragraphs includes the searched param.
const searchValue = 'para';
const array = [{authorId: '62222a1cea00a0601f200142',description: [[{title: 'English description',paragraph: 'And english paragraph!!!!',},],[{title: 'some title!!!',paragraph: 'some para!!',},],],removed: false,status: 'NEW',},{authorId: '621f97562511255efa0f135e',description: [[{title: 'EEEE',paragraph: 'aaaa',},],],removed: false,status: 'NEW',},{description: [[{title: 'TEST',paragraph: 'TESR',},],],removed: false,status: 'NEW',},{authorId: '621f97432511255efa0f135c',description: [[{title: 'My task',paragraph: 'Parapgraph 19',},],],removed: false,status: 'NEW',},];
const results = array.filter(el => {
return el.description
.map(i => {
return i.map(item => item.paragraph)
})
.every((description) => {
return description.toString().toLowerCase().includes(searchValue)
})
});
console.log(results);
I didn't tested the function, however it should work. Put the questionmarks when needed.
I think the filter should be on the array itself, since that is what you expect to be the result.
I used the some function to resolve the arrays in the object.
array?.filter(el=>el?.description.some(el2=>el2.some(el3=>el3?.paragraph.toString().toLowerCase().includes(searchValue))))
It's easier to understand if you don't have everything on one line.
Use filter to return a new array of objects where the description (inner) array has an at leasr one object that contains a paragraph containing the query.
const array=[{authorId:"62222a1cea00a0601f200142",description:[[{title:"English description",paragraph:"And english paragraph!!!!"}],[{title:"some title!!!",paragraph:"some para!!"}]],removed:!1,status:"NEW"},{authorId:"621f97562511255efa0f135e",description:[[{title:"EEEE",paragraph:"aaaa"}]],removed:!1,status:"NEW"},{description:[[{title:"TEST",paragraph:"TESR"}]],removed:!1,status:"NEW"},{authorId:"621f97432511255efa0f135c",description:[[{title:"My task",paragraph:"Parapgraph 19"}]],removed:!1,status:"NEW"}];
const query = 'par';
const out = array.filter(outer => {
// Return an object when the inner array
// of the function has some object that
// contains a paragraph containing the query
return outer.description.some(arr => {
return arr.some(inner => {
return inner.paragraph
.toLowerCase()
.includes(query);
});
});
});
console.log(out);
Additional documentation
some
have you tried .reduce()? It is combination of .map() and .filter() as you can see here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
Takes some time to get into .reduce(), but once you get it, you will like it!
I have an object with two arrays of objects being returned from an API. I need to try to map this into a new array of objects so I can group the data for the Vue v-select component. CodePen Example
fields: {
current: [
{
name: 'Date'
},
{
name: 'Time'
}
],
previous: [
{
name: 'Birthday'
},
{
name: 'Comments'
}
]
},
How can I map this into a new array of objects that looks like this?
grouped: [
{
group: "Current",
},
{
name: "Date"
},
{
name: "Time"
},
{
group: "Previous"
},
{
name: "Birthday"
},
{
name: "Comments"
},
]
Use Object.entries() to get the groups, and their values, and map them using Array.flatMap(). Create the group's object, and add it to an array with the group's items.
const flattenGroups = fields =>
Object.entries(fields)
.flatMap(([group, items]) => [{ group }, ...items])
const fields = {"current":[{"name":"Date"},{"name":"Time"}],"previous":[{"name":"Birthday"},{"name":"Comments"}]}
const result = flattenGroups(fields)
console.log(result)
Say I have an object that looks like this:
{
_id: ObjectID(1234),
name: 'Corvid',
friends: [{
name: 'Magpie',
friends: [{
name: 'Raven'
}, {
name: 'Jackdaw',
friends: [{
name: Friends.ALL_FRIENDS
}]
}]
}, {
name: 'Jay'
}]
}
Essentially, what I am trying to do is, for every entry in list of friends, replace the current object with the result of Friends.findOne({ name: obj.name }).
I am easy able to iterate through the structure like so.
function populate(obj=friends) {
if (obj.friends) {
return populate(obj.friends);
}
return friends.findOne({ name: obj.name });
}
However, what I am having trouble with is replacing that object at that specific area. How would one go about doing this?
I have a Map like this (in ImmutableJS):
{arrayOfValues: [
{one: {inside: 'first in array'}},
{one: {inside: 'second in array'}}
]}
And I want to update the value "inside" in the second entry in the "arrayOfValues" array. How can I do it? This is what I have now and it says "Uncaught Error: invalid keyPath"
theMap.update('arrayOfValues',(list)=>{
return list.setIn([1,'one','inside'],'updated value');
})
I also tried directly this and it didn't work:
theMap.setIn(['arrayOfValues',1,'one','inside'],'updated value');
After several hours of looking for the solution, I appreciate any help. Thank you.
What you are doing is correct (see this JSBin).
const orig = Immutable.fromJS({
arrayOfValues: [
{ one: { inside: 'first in array' } },
{ one: { inside: 'second in array' } },
]
});
const updated = orig.setIn(['arrayOfValues', 1, 'one', 'inside'], 'updated value');
console.log(updated.toJS());
// {
// arrayOfValues: [
// { one: { inside: 'first in array' } },
// { one: { inside: 'second in array' } },
// ]
// }
When you call orig.setIn(), it doesn't modify orig directly. That's the whole purpose of this Immutable library. It doesn't mutate the existing data but creates a new one from the existing one.
Your setIn example works as you should see in this plunkr:
http://plnkr.co/edit/1uXTWtKlykeuU6vB3xVO?p=preview
Perhaps you are assuming the value of theMap will be changed as a result of the setIn?
As these structures are immutable, you must capture the modified value in a new variable as var theMap2 = theMap.setIn(['arrayOfValues',1,'one','inside'],'updated value');
activePane is the index of Object in Array(List) that I had to modify
case CHANGE_SERVICE:
var obj = {
title: '1212121 Tab',
service: '',
tagName: '',
preDefinedApi: '',
methodType: '',
url: '',
urlParams: [{
label: '',
name: '',
value: '',
}],
headers: [{
label: '',
name: '',
value: '',
}],
};
var activePane = state.get('activePane');
var panes = state.setIn(['panes', activePane, 'service'], action.val);
return state.setIn(['panes', activePane, 'service'], action.val);