So I have an object I'm trynig to deep extend into - right now the extend function works if the lowest level is just an array, So it looks like this :
function(base, next) {
var dataEntry = base.filter(function(it) {
return it.module === next.module;
})[0];
if (dataEntry) {
var diff = next.customUrl.filter(function(it) {
return dataEntry.customUrl.indexOf(it) === -1;
});
dataEntry.customUrl = dataEntry.customUrl.concat(diff).sort();
//_.extend(dataEntry, next);
} else {
base.push(next);
}
}
And this works if the object looks like :
[
{"name" : "one", "test" : ["1","2"]},
{"name" : "two", "test" : ["1","2"]}
]
However some things had to change and now the object looks like this :
[
{"name" : "one", "test" : [{"random1" : true},{"random2" : false}] },
{"name" : "two", "test" : [{"random3" : true},{"random4" : false}]}
]
Where the keys in the array is now an array of objects, and the objects keys are random. So If there was an object with the same key - replace the value (unless its the same, otherwise push a new object inside of there.
So for that object above I would pass this to merge into it for example:
{"name" : "one", "test" : [{"random2" : true}]}
So that would change the value of random2 to true, or something like this
{"name" : "one", "test" : [{"random18" : true}] }
where that would push in random 18 like so :
[
{"name" : "one", "test" : [{"random1" : true},{"random2" : false},{"random18" : true}] },
{"name" : "two", "test" : [{"random3" : true},{"random4" : false}]}
]
Unsure how to traverse deeper and merge. Thanks for reading!!
Edit : first stab at it -
function(base, next) {
var dataEntry = base.filter(function(it) {
return it.module === next.module;
})[0];
if (dataEntry) {
var allTags = [];
allTags.push.apply(allTags, dataEntry.customUrl);
allTags.push.apply(allTags, next.customUrl);
dataEntry.customUrl = allTags;
} else {
base.push(next);
}
}
Does not work because it does not cover over objects if they are the same, just pushes into array.
http://jsfiddle.net/p08ayvv8/
this fiddle shows you how jQuery can deal with (deep) extending objects.
See http://api.jquery.com/jquery.extend/ for a detailed explaination.
It is mentionable though that when preforming the second extension jQuery will prepend the old value of test to the array, thats why I added
o1.test = o1.test[0];
Related
This question already has answers here:
Group array items using object
(19 answers)
Closed 3 months ago.
I have an array which has keys eventId and selectedNumber. In the array same eventid can be present in multiple objects but selectedNumber value will be always different. My aim is to make a nested array in which each object will have unique eventId But selectedNumber will become an array having numbers from each of those objects having the same eventId. I tried using lodash _.groupBy() method but its just combines the objects into array and add it to the value with key as eventId. I don't want that. Anyway to do it?
Input:--
[{
"eventId" : "636939dde9341f2fbbc7256e",
"selectedNumber" : "20"
},
{
"eventId" : "636939dde9341f2fbbc7256e",
"selectedNumber" : "30"
},
{
"eventId" : "63693a55e9341f2fbbc725c0",
"selectedNumber" : "50"
}]
Result:--
[{
"eventId" : "636939dde9341f2fbbc7256e",
"selectedNumber" : ["20", "30"]
},
{
"eventId" : "63693a55e9341f2fbbc725c0",
"selectedNumber" : "50"
}]
let newarr = []
oldArr.map((x,i)=>{
if(i==0){
const numArr = []
numArr.push(x.selectedNumber)
delete x.selectedNumber
x.numArr = numArr newarr.push(x)
}else{
if(oldArr[i].eventId == oldArr[i-1].eventId){
const temp = x.selectedNumber
delete x.selectedNumber
newarr[i-1].numArr.push(temp)
}else{
const numArr = []
numArr.push(x.selectedNumber)
delete x.selectedNumber
x.numArr = numArr
newarr.push(x)
}
}
})
Just reduce your input to an object, and map the object entries to the desired array format:
const input = [{
"eventId" : "636939dde9341f2fbbc7256e",
"selectedNumber" : "20"
},
{
"eventId" : "636939dde9341f2fbbc7256e",
"selectedNumber" : "30"
},
{
"eventId" : "63693a55e9341f2fbbc725c0",
"selectedNumber" : "50"
}];
const result = Object.entries(input.reduce((a, {eventId, selectedNumber}) => {
a[eventId] = a[eventId] || [];
a[eventId].push(selectedNumber)
return a;
}, {})).map(([eventId, selectedNumber]) => ({ eventId, selectedNumber }));
console.log(result);
Instead of creating the intermediate lookup object, you could directly reduce to an array, but it will have a negative impact on the solution's time complexity.
I'm parsing a JSON message which looks something like:
{
staff : [
{name : 'John', department : 'Math'},
{name : 'Sally', department : 'Science'},
],
students : [
{name : 'Bob', department : 'Law'},
{name : 'Lisa', department : 'IT'}
]
}
From which I'd like to pull out an array of each separate value.
i.e.
names -> ['John', 'Sally', 'Bob', 'Lisa']
At the moment I'm doing something like
var names = [];
msg.staff.forEach(function(e) { names.push(e.name) })
msg.students.forEach(function(e) { names.push(e.name)})
This feels overly verbose, just wondering if there's a cleaner way to approach this (for every attribute). I'm already including lodash in this project.
You can use _.pluck to get the value of a property of each object in an array:
_.pluck(obj.staff.concat(obj.students), 'name')
Your instinct is right; you don't need a mutable array to do this with lodash.
_(obj).map().flatten().pluck('name').value();
This version works for any number of array values in o.
JSBin
Edit missed that you had lodash available, will leave this vanilla JS version here anyway.
You could use map to be more concise:
var directory = {
staff : [
{name : 'John', department : 'Math'},
{name : 'Sally', department : 'Science'},
],
students : [
{name : 'Bob', department : 'Law'},
{name : 'Lisa', department : 'IT'}
]
};
var names = directory.staff.concat(directory.students).map(function(person) {
return person.name;
});
If you don't know the individual key names before hand, you could do:
Object.keys(directory).map(function(key) {
return directory[key]
}).reduce(function(p,c){
return p.concat(c)
}).map(function(person) {
return person.name;
});
I didn't catch the requirement of getting an array of all values stored under each key, this should do it though:
Object.keys(directory).map(function(key) {
return directory[key];
}).reduce(function(p,c) {
return p.concat(c);
}).reduce(function(p, c) {
Object.keys(c).forEach(function(oKey) {
if(p[oKey]) p[oKey].push(c[oKey]);
else p[oKey] = [c[oKey]];
});
return p;
}, {});
This returns the following:
{
"name":["John","Sally","Bob","Lisa"],
"department": ["Math","Science","Law","IT"]
}
Below is my json structure. On success of collection.fetch() i'm looping through the structure.
Currently i use
this.collection.each(function(model) { .. }
How do i obtain key name like plants, animals and instead loop using the names.
JSON
var jsonObj = { // 0 - recommended , 1 - New
"plants" : [
{
"title" : "title1",
"desc": "description.."
},
{
"title" : "titl2",
"desc": "description."
}
],
"animals" : [
{
"title" : "title1",
"desc": "description.."
},
{
"title" : "titl2",
"desc": "description."
}
]
};
Snapshot of collection
This would work, but you'd use a normal for loop, not "each":
for(i in jsonObj){
alert(i);
}
here is a fjsfiddle: http://jsfiddle.net/r5nwP/
Is that what you're after?
You can use the underscore keys to get a list of names:
var thenames =_.keys(yourobject);
In this case thenames will contain a list of the keys you are looking for. Here is the documentation for it:
http://underscorejs.org/#keys
keys_.keys(object)
Retrieve all the names of the object's properties.
_.keys({one : 1, two : 2, three : 3});
=> ["one", "two", "three"]
I have the following JSON Object being loaded into my application and stored into a var called obj:
{
"items" : [
{
"name" : "item-1",
"group" : [
{
"groupName" : "name-1",
"groupPosition" : 2
},
{
"groupName" : "name-2",
"groupPosition" : 1
}]
},
{
"name" : "item-2",
"group" : [
{
"groupName" : "name-1",
"groupPosition" : 1
},
{
"groupName" : "name-2",
"groupPosition" : 2
}]
}]
}
I then do the following to go through it:
var groups = new Array();
var items = new Array();
$.each(obj.items, function(i,r){
var itemName = r.name;
$.each(r.group, function(index, record){
if ($.inArray(record.groupName) == -1) {
groups.push(record.groupName);
$('body').append('<div id="record.groupName"></div>');
}
$('#'+record.groupName).append('<div id="itemName">itemName</div>');
// At this point I'm stuck as the items get added in order of iteration,
// not according to their record.groupPosition value.
});
});
There will eventually be several hundred "items" each contained within an unset number of "groups".
The trouble I'm having is how to iterate through the JSON object using jQuery or good ol'JavaScript and display the items in the correct position within each group as the items and groups won't be listed inside the JSON object in sequential order.
Any help would be greatly appreciated!
Thank you.
Why not just give the group items the position index like this:
{
"items" : [
{
"name" : "item-1",
"group" : {
2:{
"groupName" : "name-1",
"groupPosition" : 2
},
1:{
"groupName" : "name-2",
"groupPosition" : 1
}}
},
{
"name" : "item-2",
"group" : {
1:{
"groupName" : "name-1",
"groupPosition" : 1
},
2:{
"groupName" : "name-2",
"groupPosition" : 2
}}
}]
}
Assuming you have a variable which is assigned to this:
var data = ...
you could use the $.each() method:
$.each(data.items, function(index, item) {
// here item.name will contain the name
// and if you wanted to fetch the groups you could loop through them as well:
$.each(item.group, function(i, group) {
// here you can use group.groupName and group.groupPosition
});
});
Arrays ([]) in javascript are 0 index based and preserve their order when you are iterating over them.
If I understood correctly your problem it is not about the sorting it self but how to link them to your dom nodes, solution: use classes with numbers.
For example:
$(".group"+items[1].group[0].grouposition").append(items[1].group[0].name);
// this will give append to the element with class="group1"
If you join this with having the html structure that is being generated to match the same names, then it won't be a problem and you don't have to sort them
Square brackets is an array, and curly brackets are objects correct?
What exactly is this data structure:
Some.thing = [ {
"swatch_src" : "/images/91388044000.jpg",
"color" : "black multi",
"inventory" : {
"F" : [ 797113, 797114 ],
"X" : [ 797111, 797112 ]
},
"images" : [ {
"postfix" : "jpg?53_1291146215000",
"prefix" : "/images/share/uploads/0000/0000/5244/52445892"
}, {
"postfix" : "jpg?53_1291146217000",
"prefix" : "/images/share/uploads/0000/0000/5244/52445904"
}, {
"postfix" : "jpg?53_1291146218000",
"prefix" : "/images/share/uploads/0000/0000/5244/52445909"
} ],
"skus" : [ {
"sale_price" : 199,
"sku_id" : 797111,
"msrp_price" : 428,
"size" : "s"
}, {
"sale_price" : 199,
"sku_id" : 797112,
"msrp_price" : 428,
"size" : "m"
}, {
"sale_price" : 199,
"sku_id" : 797113,
"msrp_price" : 428,
"size" : "l"
}, {
"sale_price" : 199,
"sku_id" : 797114,
"msrp_price" : 428,
"size" : "xl"
} ],
"look_id" : 37731360
} ];;
Some.thing is an array [] containing a single object {}. Some of the properties of this object are strings while others are arrays.
The single object appears to be describing a product.
Yes, an array of objects with nested arrays within. (or in this case one single element contained within an array.)
Some.thing[0] refers to everything you have listed. From there, you have an object containing:
var obj = Some.thing[0];
obj.swatch_src // contains "/images/91388044000.jpg"
obj.color // contains "black multi"
...
obj.inventory // (another object
obj.inventory.F // array of [797113, 797114]
...
obj.images // array of objects
obj.images[0].postfix // contains "jpg?53_1291146215000"
obj.images[0].prefix // contains "/images/share/uploads/0000/0000/5244/52445892"
...
This is captured from Chrome Console. You can try it yourself :)
Yes, this is called JSON: JavaScript Object Notation.