Sorting of Arrays in Object with recursive search - javascript

I am trying to sort every Array by Name in an JSON-Object using Node.js.
I manage to sort just the Array with Underscore.js, but how can I input the whole Object and just get the Object back finished sorted?
Thinking about looking through the object recursively for Arrays and sort every one of them, but how can I do that?
Here is an example Object with just sorting the Array:
var _ = require("./underscore.js")
var jsonObject = { "Configuration":{
"$":{
"xmlns":"http://www.example.com/"
},
"ApplicationInstance":{
"Description":"Description text here.",
"Name":"Server1",
"Class":"System",
"Visibility":"System",
"CustomerCreated":"0",
"Active":"0",
"IntroducedIn":{
"$":{
"xsi:nil":"true",
"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance"
}
},
"Property":[
{
"Description":"JMS publisher destination type.",
"Name":"jmsJBossPublisher.destinationType",
"Class":"System",
"Visibility":"System",
"LanguageIndependantDescriptionKey":"ActivityGateway-JMSSenderConfiguration.jmsJBossPublisher.destinationType.DESCKEY",
"LanguageIndependantNameKey":"ActivityGateway-JMSSenderConfiguration.jmsJBossPublisher.destinationType.NAMEKEY",
"CustomerCreated":"1",
"Active":"0",
"IntroducedIn":"1.1",
"AttributeValue":"QUEUE",
"AttributeDataTypeName":"String"
},
{
"Description":"jmsConnectionFactory properties.",
"Name":"jmsConnectionFactory.jndiNameForJmsConnectionFactory",
"SecurityClass":"System",
"Visibility":"System",
"LanguageIndependantDescriptionKey":"ActivityGateway-JMSSenderConfiguration.jmsConnectionFactory.jndiNameForJmsConnectionFactory.DESCKEY",
"LanguageIndependantNameKey":"ActivityGateway-JMSSenderConfiguration.jmsConnectionFactory.jndiNameForJmsConnectionFactory.NAMEKEY",
"CustomerCreated":"1",
"Active":"0",
"IntroducedIn":"1.1",
"AttributeValue":"ConnectionFactory",
"AttributeDataTypeName":"String"
}
],
"ServerId":"1",
"ApplicationName":"ActivityGateway",
"InstanceID":"1"
}
}
};
console.log(_.sortBy(jsonObject.Configuration.ApplicationInstance.Property,'Name'))

_.sortBy returns a cloned array, so you'll need to override the previous value.
Try adding this line:
jsonObject.Configuration.ApplicationInstance.Property = _.sortBy(jsonObject.Configuration.ApplicationInstance.Property,'Name')

Related

How to get JSON values of multiple keys of the same name

I have a JSON data set as follows:
{
"content":[],
"layout":[],
"trail":[
{
"content":[
{
"type":"image",
"media":[
{
"type":"image/jpg",
"width":593,
"height":900,
"url":"https://live.staticflickr.com/65535/48208920877_e6b234d3ea_c_d.jpg",
"flickr":{
"flickr-post":"https://www.flickr.com/photos/riketrs/48208920877",
"flickr-album":"https://www.flickr.com/photos/riketrs/albums/72157709130951466"
}
}
]
},
{
"type":"image",
"media":[
{
"type":"image/jpg",
"width":1600,
"height":900,
"url":"https://live.staticflickr.com/2817/33807326532_91013ef6b1_h_d.jpg",
"flickr":{
"flickr-post":"https://www.flickr.com/photos/146758538#N03/33807326532",
"flickr-album":"https://www.flickr.com/photos/146758538#N03/albums/72157681438471236"
}
}
]
}
],
"colors":{
"c0":"#1e1e1d",
"c1":"#78736f",
"c2":"#b2a89f"
}
}
]
}
I would like to console.log the "url" key for each of the images shown here.
(https://live.staticflickr.com/65535/48208920877_e6b234d3ea_c_d.jpg and https://live.staticflickr.com/2817/33807326532_91013ef6b1_h_d.jpg)
I tried some code but I'm very new to JSON in general, I've looked at some other answers to do with JSON but I'm not quite sure how to achieve what I want.
JSFiddle: https://jsfiddle.net/fj6qveh1/1/
I appreciate all advice, including links to other answers that I potentially missed.
Thank you!
url is a property of an object. There can be many of these in a media array. (This data only shows one object per array.) media itself is an property of objects inside the content array.
Use map, and flatMap.
map to return the URL values from the objects in media, and flatMap to return a flat array of the nested arrays returned by map.
const data={content:[],layout:[],trail:[{content:[{type:"image",media:[{type:"image/jpg",width:593,height:900,url:"https://live.staticflickr.com/65535/48208920877_e6b234d3ea_c_d.jpg",flickr:{"flickr-post":"https://www.flickr.com/photos/riketrs/48208920877","flickr-album":"https://www.flickr.com/photos/riketrs/albums/72157709130951466"}}]},{type:"image",media:[{type:"image/jpg",width:1600,height:900,url:"https://live.staticflickr.com/2817/33807326532_91013ef6b1_h_d.jpg",flickr:{"flickr-post":"https://www.flickr.com/photos/146758538#N03/33807326532","flickr-album":"https://www.flickr.com/photos/146758538#N03/albums/72157681438471236"}},{type:"image/jpg",width:1600,height:900,url:"https://live.dummyimage.com/2817/dummy.jpg",flickr:{"flickr-post":"https://www.flickr.com/photos/146758538#N03/33807326532","flickr-album":"https://www.flickr.com/photos/146758538#N03/albums/72157681438471236"}}]}],colors:{c0:"#1e1e1d",c1:"#78736f",c2:"#b2a89f"}}]};
const content = data.trail[0].content;
const urls = content.flatMap(obj => {
return obj.media.map(inner => inner.url);
});
console.log(urls)
The easiest way is to use map function. Given that you are very new to programming (the solution has little to do with JSON itself, since the first step is to parse JSON string to a JavaScript object), it would be better if you try yourself. But you start with
let urls = trail["content"].map(x => x["media"][0]["url"])
for more about map function look here
There is a table in the table so for each table:
for(let i in trail){
var content = trail[i]["content"];
content.forEach(content => content.media.forEach(media => console.log(media.url)))
}
To access object properties, you can use a dot (.), and to access an array element, you use its index in square brackets ([]). So you just keep repeating these steps as necessary until you get to the content you're looking for.
Here's how that looks on a simplified version of your object, using the forEach method of arrays to apply a custom function to each item in the content array:
const json = getJson();
json.trail[0].content.forEach(item=>console.log(item.media[0].url));
function getJson(){
let obj = {
"trail": [{
"content": [
{ "media": [{ "url":"image #65535/48208920877_e6b234d3ea_c_d.jpg" }]},
{ "media": [{"url":"image #2817/33807326532_91013ef6b1_h_d.jpg"}]}
]
}]
};
return obj;
}

revise deeply nested JSON array in DOM

I have an HTML page that contains a stringified JSON object. The object has this structure:
{
"x":{
"key1":[],
"key2":{},
"keyN":{},
"myKey":{
"randomID238492":{
"items":[
{ "value":"zzzz" },
{ "value":"aaaa" },
{ ...}
]
}
}
}
}
I want to replace this object with one in which the "items" array has been sorted. Here is what I will and won't know about the object:
"myKey" and "items" will always be the relevant object keys
"myKey" will contain only one random ID, and the "items" key will always be its first child
I won't know the order of "myKey" in the object.
I won't know the true randomID under which "items" nests.
Is there a clear, efficient way to replace this JSON object with one in which "items" has been sorted? Right now, I do it by using this jQuery function after the page has rendered:
$(function() {
var myData = $( "#myJSON_string" )[0]; // <script> node that contains the string
var myDataJSON = JSON.parse(myData.innerText); // JSON string
var myKeyJSON = myDataJSON["x"]["myKey"]; // object
var myArr = myKeyJSON[Object.keys(myKeyJSON)[0]]["items"]; // array to sort
// Now sort and revise. I'm leaving myCompare() out of the example for brevity
myKeyJSON[Object.keys(myKeyJSON)[0]]["items"] = myArr.sort(myCompare);
myDataJSON["x"]["myKey"] = myKeyJSON;
myDataJSON = JSON.stringify(myDataJSON);
myData.innerText = myDataJSON;
});
This approach works, but it seems rather labored. It might be better, for example, if I could revise the JSON object "in place" without parsing it and then re-stringifying it.
Many SO posts, like this one, speak to the general question of how to sort a JSON array. But I can't see that any speak to the specific question posed here.

array1.splice(1,1) is removing data from array2 which I have created using array1.slice(0)

I have JSON data, and I have converted that data into an array of objects and have assigned that array into an another array using the .slice(0) method.
When I am trying to remove some element from the assigned array it is removing the same element from the original element.
But I don't want to change my original array at any point of time.
var values = [
{
"timeId":"201501010100",
"Week1Volume": 2454721,
"Week2Volume": 7017731,
"Week3Volume": 5656528,
"Week4Volume": 2472223
},
{
"timeId":"201501010200",
"Week1Volume": 2454721,
"Week2Volume": 7017731,
"Week3Volume": 5656528,
"Week4Volume": 2472223
},
{
"timeId":"201501010300",
"Week1Volume": 1999120,
"Week2Volume": 5355235,
"Week3Volume": 5120254,
"Week4Volume": 2607672
}]; // This is my JSON data
var weekNames = d3.keys(values[0]).filter(function(key) { return key !== "timeId" && key!== "weeksVolume";});;
values.forEach(function(d) {
d.weeksVolume = weekNames.map(function(name) { return {name: name, value: +d[name]}; });
}); // original array
var data = values.slice(0); // Data is my new array
function removeFromSecondArray(){
// Here I am removing the first object of weekVolumes from each object of the array
data.forEach(function(d) {
d.weeksVolume.splice(1,1);
});
};
But after execution of above function 1st element of "values" also got removed.
Perhaps this is your problem:
When you are copying the JSON object you are creating the reference to an old object. So, any operation done on one reference will be performed on both objects.
So you should apply a deep copy here like this and then apply the further manipulations.
var newObj=JSON.parse(JSON.stringify(oldObj));
I hope this will help you. This is a deep copy. It will not create the reference.

angular, strip unused data before doing a lodash _.isEqual

So I have am trying to compare 2 objects using lodash's _.isEqual method, I have pretty straight forward function that checks like so
function findMatchingQuery(savedSearch) {
if (_.isEqual(savedSearch.data.document.query, $scope.searchResults.minify())) {
return true;
}
}
The data has changed a bit and I need to pull out a piece of data inside before I do a compare.
So the each of those objects has this format -
{
"name": "item name",
"showMore": boolean,
"filters": []
}
And what I would like to do is strip out the showMore node. I tried to add the some vars using _.remove, however it seems this does not work because remove is looking for a key and value.
var modifiedSavedSearch = _.remove(savedSearch.data.document.query, { "showMore" });
var modifiedCurrentSearch = _.remove($scope.searchResults.minify(), { "showMore" });
Is there a simple way to strip away those parts of the object before running the _.isEqual on them? Doesn't have to be lodash. Thanks!
You can delete the attribute, like:
delete savedSearch.data.document.query.showMore
You can use _.omit to remove it, or you can use _.pick to pick the rest of the attributes
Yeah, omit should do what you are looking for:
var modifiedSavedSearch = _.omit(savedSearch.data.document.query, { "showMore" });
If you want to get rid of it completely, you can do the following:
// assuming this is your variable
var myVar = {
"name": "item name",
"showMore": boolean,
"filters": []
};
// delete the unwanted property
delete myVar.showMore;

Change the name of keys while creating an array

I have the response in the following format after doing groupby in solr query. I am using solr version 3.5
"grouped":{
"channel_id":{
"matches":48,
"ngroups":26,
"groups":[{
"groupValue":"204",
"doclist":{"numFound":1,"start":0,"docs":[
{
"channel_name":"ZeeTv",
"channel_num":4,
"title":"The Name",
"channel_id":"204"
}},
{
"groupValue":"166",
"doclist":{"numFound":2,"start":0,"docs":[
{
"channel_name":"Sony",
"channel_num":2,
"title":"The Name",
"channel_id":"166",
{
"channel_name":"Sony",
"channel_num":2,
"title":"The Puzzle",
"channel_id":"166"
}}]}}
I am taking the response in an array in the following way :
for(var chl in data.grouped.channel_id.groups) {
config['playlist'].push(data.grouped.channel_id.groups[chl]['doclist']['docs']);
}
Thus an individual array of each groupValue is formed. The struture of the array is:
"0"=>{"0"=>"value"},"1"=>{"0"=>"result1","1"=>"result2"}
But i want to change the key name i.e. "0","1" to the groupValue from the response while creating an array so that i can do config['playlist']['166'] to check all the shows for this channel_id from the array. Can this be done and if so how. I am expecting the following :
"204"=>{"0"=>"value"},"166"=>{"0"=>"result1","1"=>"result2"}
Also if possible can the solr query be made such that the channel_num in the response comes in ascending order i.e. first result for channel_num 2 and then 4. I have done groupby:channel_id
What about that?
for(var chl in data.grouped.channel_id.groups) {
config['playlist'][data.grouped.channel_id.groups[chl].groupValue] = data.grouped.channel_id.groups[chl]['doclist']['docs'];
}
Push is there to add an element at the end of an array. But any Javascript object is just a hash table, so you can use it that way.
By the way, you can make the code simpler with a for each :
for each(var chl in data.grouped.channel_id.groups) {
config['playlist'][ch1.groupValue] = ch1['doclist']['docs'];
}
Pikrass has answered correctly... as far as ordering with channel_num is concerned try adding the following in your query:
&sort=channel_num asc

Categories