find and update property of nested object with lodash - javascript

I have been scanning through stackoverflow topics and couldn't find answer to the problem i am having.
What i need to do is to find object inside nested (2 depths) array by some of the values and then update other of its values. I managed to put together the finding and also setting seems to work, the problem is that lodash does return main object and it updates main object, not the nested one i actually need.
lets take this structure:
var data = [
{
name: 'I',
status: "0",
categories: [
{
name: 'I1',
status: "0",
specifics: [
{
name: "I1a",
status: "0",
}
]
}
]
}
];
i need to find object inside specifics by its name and then update its status.
so lets try simple find first:
var find = _.find(data, { categories: [ { specifics: [ { name: "I1a" } ] } ]});
this is working but it returns the object with name: I so first main one.
so then if i try to update with this:
var set = _.set(_.find(data, { categories: [ { specifics: [ { name: "I1a" } ] } ]}), 'status', "1");
It also does work but it updates status of I instead of what i was looking for which is I1a.
Is there a way to make finding and therefore setting to return / work on actually queried object ?
var data = [
{
name: 'I',
status: "0",
categories: [
{
name: 'I1',
status: "0",
specifics: [
{
name: "I1a",
status: "0",
}
]
}
]
}
];
var find = _.find(data, { categories: [ { specifics: [ { name: "I1a" } ] } ]})
console.log('find', find);
var set = _.set(_.find(data, { categories: [ { specifics: [ { name: "I1a" } ] } ]}), 'status', "1");
console.log('set', set);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

Related

Why is my object formulating differently in the console than it is when I run it through Tidy JS?

My Array of Objects is not appearing the way I want it to when I print it to the console. When I put it through Tidy JS, it formats it correctly. When I print it to the console, it looks incorrect.
What I want it to look like is:
Array
Object
Key:Value
Key:Value
Array
Object
Object
Object
Object
But instead its prints out how it does in this codepen:
https://codepen.io/anon/pen/qLrgKg
Any ideas as to why formatting it like it is in this codepen instead of how I want it to be?
var ArrayOfBlocks1 = [
{
ID:"1",
block: "block1",
BlockElements: [
{ blockElement1: { QuestionID: "1" } },
{ blockElement2: { QuestionID: "2" } },
]
},
{
ID:"2",
block: "block2",
BlockElements: [
{ blockElement1: { QuestionID: "1" } },
{ blockElement2: { QuestionID: "2" } }
]
},
{
ID:"3",
block: "block3",
BlockElements: [
{ blockElement1: { QuestionID: "1" } },
{ blockElement2: { QuestionID: "2" } }
]
}
];
You are printing the first element in the array rather then the whole array.
Change line 42 from console.log(ArrayOfBlocks1[0]) to console.log(ArrayOfBlocks1)

How to include elements of an array in another array?

So for example I have a MAIN array with all the information I need:
$scope.songs = [
{ title: 'Reggae', url:"#/app/mworkouts", id: 1 },
{ title: 'Chill', url:"#/app/browse", id: 2 },
{ title: 'Dubstep', url:"#/app/search", id: 3 },
{ title: 'Indie', url:"#/app/search", id: 4 },
{ title: 'Rap', url:"#/app/mworkouts", id: 5 },
{ title: 'Cowbell', url:"#/app/mworkouts", id: 6 }
];
I want to put only certain objects into another array without typing in each of the objects so the end result will look like
$scope.array1 = [
{ title: 'Reggae', url:"#/app/mworkouts",id: 1 },
{ title: 'Cowbell', url:"#/app/mworkouts",id: 6 }
];
I have tried this with no luck:
$scope.array1 = [
{ $scope.songs[1] },
{ $scope.songs[6] }
];
I will have to do a bunch of these so typing in each object would take forever, is there any faster way to do this? Thanks in advance :)
You need to do something like this:
$scope.array1 = $scope.songs.filter(function (song) {
return (song.title == "Reggae" || song.title == "Cowbell");
});
Here, the filter function will give you a filtered new array to be replaced for the original scope value.
Or in simple way, using the array indices, you can use:
$scope.array1 = [ $scope.songs[0] , $scope.songs[5] ];
You need to remove the braces since it's already an object. Although the array index starts from 0 so change index value based on 0.
$scope.array1 = [
$scope.songs[0] ,
$scope.songs[5]
];

Compare value and add if matches to an array

Im trying to merge 2 data sources in 1, I wanna loop through them and if a specefic value matches than add it to the first object with the same value and add the in the emty array what is already there. No matter how much objects I have.
So lets say I have this information
Source 1
one = {
"teams": [
{
name: 'ABC',
members: [],
rooms: '0'
},
{
name: 'DEF',
members: [],
rooms: '1'
}
]
}
Source 2
two = {
"persons": [
{
name: 'Foo',
gender: 'male',
room: '1'
},
{
name: 'Bar',
gender: 'female',
room: '2'
}
]
}
And what I want is that the 'persons' array merge to the members array if the 'room and rooms' value matches.
What I would assume is something similar like this:
for(var i = 0 ; i < two.persons.length; i++) {
if (one.teams[i].rooms == two.persons[i].room) {
data.teams[i].members.push(two.persons[i]);
}
}
using higher order methods you can do:
one = {
"teams": [
{
name: 'ABC',
members: [],
rooms: '0'
},
{
name: 'DEF',
members: [],
rooms: '1'
}
]
};
two = {
"persons": [
{
name: 'Foo',
gender: 'male',
room: '1'
},
{
name: 'Bar',
gender: 'female',
room: '2'
}
]
};
var ttt = one.teams.map(function(x){
var roomVal= x.rooms;
x.members = two.persons.filter(function(t){
return t.room == roomVal});
return x;
})
one.teams = ttt;
console.log(one)
The problem with your code is that once you iterate the two array, then you do not go back and see if the previous element matched with the current one.
For example, if [0] on each arrays does not match and you iterate to index [1] in the for-loop, you do not have a way to check if two[1] matched one[0].
To do a complete search, you could directly iterate the arrays for each value of two:
two.persons.forEach(function(person) {
one.teams.forEach(function(team) {
if (team.rooms == person.room) {
team.members.push(person);
}
});
});
There are many strategies to do this. But most important you should iterate each array separately. I would use an Array.forEach();
one.teams.forEach(function (team, teamsIndex, teamsArray) {
two.persons.forEach(function (person, personsIndex, personsArray) {
if (team.room == person.room) {
// Do what you need to do.
}
});
});
Didn't check syntax so be aware to read Array.forEach(); documentation.

Divide a Javascript Array and subarrays In 2 arrays

I have this array:
var myArray = [
{ familyName: 'one', subfamilies:
[ { subfamilyName: 'subOne', subItems:
[ { name: 'subOne', code: '1' },
{ name: 'subTwo', code: '2' }
] }
]
},
{ familyName: 'two', subfamilies:
[ { subfamilyName: 'subTwo', subItems:
[ { name: 'subOne', code: '1' },
{ name: 'subTwo', code: '2' },
{ name: 'subTwo', code: '3' }
] }
]
}
]
I need to divide that array in two diferent arrays with the same length if possible (my real array is so much longer), but I am having some problems getting it done. I create 2 blank array and, with for sentence read all the items. First I push the subItems in one blank array, but cannot get the way to create a new subFamily in a blank array variable and then push the sutItems array.
How can be this done?
Thanks a lot in advance.
var myOtherArray = myArray.splice(myArray.length / 2 | 0);

Iterating a javascript collection and adding a sort order

I have a tree in javascript which has multiple root elements and nested children.
Here's the object:
[{
_id: '546d30905d7edd1d5169181d',
name: 'first'
children: []
}, {
_id: '546d30905d7edd1d2169181d',
name: 'second'
children: []
}, {
_id: '446d30905d7edd1d5169181d',
name: 'third',
children: [{
_id: '446d30905d7e2d1d5169181d',
name: '3child',
children: []
}, {
_id: '446d30915d7e2d1d5169181d',
name: '3child2',
children: [{
_id: '546d30905d7edd1d2569181d',
name: 'second2',
children: []
}]
}]
}, {
_id: '546d30995d7edd1d5169181d',
name: 'fourth',
children: []
}]
This is a truncated document that's being stored in MongoDB using materialized path. The issue is that I need to add a 'sorting' ability, so nodes in the same root can be sorted.
I want to iterate this tree and apply a sort_value such as node['sort_value'] = 0, etc.
Each level will have it's own sort order, starting at 0.
I can simply iterate the tree recursively:
function iterate(items) {
_.each(items, function(page, key) {
if (items.children.length > 0) {
iterate(items.children);
}
});
}
However, I can't figure out how to keep track of the sort orders and also update the object's to include the sort_value field.
Any help would be greatly appreciated! Thank you
I did it so that I used array key for sorting and "synchronized" it with object property (because I needed it saved to DB and restored after) and it works as a charm :)
So something like this, pseudo:
var unsorted = [
0:{"sort_key": "0", "data":"dataaa 0"},
1:{"sort_key": "1", "data":"dataaa 1"},
...
n:{"sort_key": "n", "data":"dataaa n"}
];
function_sort(unsorted){
...
return sorted = [
0:{"sort_key": "n", "data":"dataaa y"},
1:{"sort_key": "44", "data":"dataaa x"},
...
n:{"sort_key": "0", "data":"dataaa z"}
];
}
save = function_save(sorted){
...update sort_key as array key...
return for_saving;
}

Categories