Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I can ordering a-z using the .sort() method in javascript, but I would get a JSON like this: (With a "A-Z" index containing the result)
data: {
"A": [
{
"name": "Anh Tuan Nguyen",
"age": 28
},
{
"name": "An Nguyen",
"age": 20
},
],
"Z": [
{
"name": "Zue Dang",
"age": 22
},
{
"name": "Zoom Jane",
"age": 30
},
]
}
var names = [{name:"a1"},{name:"a2"},{name:"b1"},{name:"b2"}.....];
var data = {};
for (var i = 0; i < names.length; i++) {
var n = names[i].name.subStr(0,1);
if (data[n] == null)
data[n] = [];
data[n].push(names[i]);
}
There is no way to sort a JSON data structure, however, we can do it by using the following process:
Get your data keys with Object.keys(myResults.data)
Sort you keys
Create a reduce function to transform your ordered keys into an ordered object
The snippet is here, I hope it helps:
var myResults = {
data: {
C: [
{
"name": "Kevin Doe",
"age": 22
}
],
A: [
{
"name": "Alex Doe",
"age": 31,
}
],
B: [
{
"name": "Boris Doe",
"age": 22
},
{
"name": "Birdo Doe",
"age": 30
},
]
}
};
var originalData = myResults.data;
// 1. get the keys
var dataKeys = Object.keys(originalData);
// 2. sort the keys
var sortedKeys = dataKeys.sort();
// 3. create the object again
var orderedData = sortedKeys.reduce(function(result, key) {
return Object.assign(
{},
result,
{ [key]: myResults.data[key] }
);
}, {});
document.getElementById('original').innerHTML = JSON.stringify(originalData);
document.getElementById('sorted').innerHTML = JSON.stringify(orderedData);
h3 {
margin: 0;
}
code {
display: block;
margin-bottom: 15px;
padding: 10px;
background-color: #f9f9f9;
}
<h3>Original Data</h3>
<code id="original"></code>
<h3>Ordered Data</h3>
<code id="sorted"></code>
JavaScript objects are not ordered. If you want to iterate over an object's properties, you can sort the keys and then retrieve your values:
const result = {
data: {
Z: [],
F: [],
A: [],
D: []
}
};
Object
.keys(result.data)
.sort()
.map(key => console.log(key, result.data[key]));
UPDATE:
Exist a JavaScript library that make It possible: Lodash Utilities (https://lodash.com/docs/4.17.4). Contain methods for .sort() JSON (no Arrays) and a method to obtain the JSON for I asked in this question. I only did this:
//First, order my JSON alphabetically with _.sortBy method (I can even order by a nested property in my JSON)
var order = _.sortBy(require('./names'), function (el) { return el.name });
//Second, I group my order result by the first letter of my property 'name' in my JSON
var list = _.groupBy(order, (b) => b.name[0].toUpperCase());
This is my input:
[
{"name":"Mark"},
{"name":"Jul"},
{"name":"Alicia"},
]
This is my output:
[
"A": [
{
"name": "Alicia"
}
],
"J": [
{
"name": "Jul"
},
],
"M": [
{
"name": "Mark"
},
]
I hope this help to somebody!
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 months ago.
Improve this question
Given this input:
const paths = ["src", "src/components", "src/components/index.ts", "src/utils", "src/configuration/config.ts", "another/file.ts"];
I need to create a function or a data structure that returns a Tree with the following structure.
[
{
"id": "src",
"level": 1,
"childrens": [
{
"id": "src/components",
"level": 2,
"childrens": [
{
"id": "src/components/index.ts",
"level": 3,
"childrens": []
}
]
},
{
"id": "src/utils",
"level": 2,
"childrens": []
},
{
"id": "src/configuration",
"level": 2,
"childrens": [
{
"id": "src/configuration/config.ts",
"level": 3,
"childrens": []
}
]
}
]
},
{
"id": "another",
"level": 1,
"childrens": [
{
"id": "another/file.ts",
"level": 2,
"childrens": []
}
]
}
]
I tried everything but I can't make it work, so if anyone can help I would appreciate it a lot.
Thank you.
First, here's the solution based on this answer: https://stackoverflow.com/a/57344801/3807365.
Explanation below.
const paths = ["src", "src/components", "src/components/index.ts", "src/utils", "src/configuration/config.ts", "another/file.ts"];
let agg = {
temp: []
};
paths.forEach(path => {
path.split('/').reduce((agg, part, level, parts) => {
if (!agg[part]) {
agg[part] = {
temp: []
};
agg.temp.push({
id: parts.slice(0, level + 1).join("/"),
level: level + 1,
children: agg[part].temp
})
// console.log(agg)
}
return agg[part];
}, agg)
})
var result = agg.temp;
console.log(result)
.as-console-wrapper {
max-height: 100% !important;
}
Explanation:
Given a path (splitted to parts) and the result which is an empty array []
we are building this kind of object (helper object!):
{
"src" : {
"utils" : {
"file.ts" : {}
},
"components" : {
"file.ts" : {}
}
},
"another": {
"file.ts" : {}
}
}
We do this step by step as we go on each part of the path.
And we do this to each path building this lovely tree.
Simple enough.
But as we do, we are creating arrays in the result object (which is under property temp) - arrays of items of the same level in the format {id, level, children}.
Finally, we ignore this entire helper tree and only return the first level array - which is the result (under property temp).
Once you realize this, you can see the possible error in this method. Can you spot it? What kind of path name will "mess" with the result?
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have a json file:
[
{
"name": "Cocktail 1",
"ingredients": {
"rum": 12,
"coke": 48
}
}, {
"name": "Cocktail 2",
"ingredients": {
"gin": 24,
"tonic": 60
}
}]
Now I want to get a list of the keys of each "name" object. At the end there should be ths list
var mydata[0] = rum
var mydata[1] = coke
var mydata[2] = gin
var mydata[3] = tonic
and save it into an array.
What i have tried
var mydata = JSON.parse("jsonstring").ingredients;
hope this is understanable?
for each data in the array (map)
you want the ingredient part (.ingredients),
extract the keys (Object.keys)
and flatten the array (.flat())
array.map(a => a.ingredients).map(a => Object.keys(a)).flat();
You may prefer loop style. the only difference is flattening occurs with ... operator.
var results = [];
for (let a of array) {
results.push(...Object.keys(a.ingredients))
}
My proposition is :
'use strict'
const array = [
{
"name": "Cocktail 1",
"ingredients": {
"rum": 12,
"coke": 48
}
},
{
"name": "Cocktail 2",
"ingredients": {
"gin": 24,
"tonic": 60
}
}
]
const mydata = array.map((val) => {
return Object.keys(val.ingredients);
}).flat();
console.log(mydata)
// expected output: Array ["rum", "coke", "gin", "tonic"]
// Now you can get :
var mydata[0] = rum
var mydata[1] = coke
var mydata[2] = gin
var mydata[3] = tonic
Hope that help you? Thank
This question already has answers here:
Sort JavaScript object by key
(37 answers)
Closed 3 years ago.
I have a list for order of field to display
field_order = ["name", "age", "birthday"]
I got a list of objects like this
_data_set = {
"age": 23,
"birthday": "2000-12-12"
"name": "A"
}
I need to order Object keys according to field_order.
Expected result:
_data_set = {
"name": "A",
"age": 23,
"birthday": "2000-12-12"
}
Key order is chronological in JavaScript since ES2015, so we can order like so:
There's a nice article on this: property-traversal-order-es6
field_order = ["name", "age", "birthday"]
_data_set = {
"age": 23,
"birthday": "2000-12-12",
"name": "A"
};
let result = field_order.reduce( (obj, v) => {
obj[v] = _data_set[v];
return obj;
}, {});
console.log(result);
At first you need to sort and then just create an object with desired order of keys:
let field_order = ["name", "age", "birthday"];
let _data_set = {
"age": 23,
"birthday": "2000-12-12",
"name": "A"
}
let order = {name: -1, age: 0, birthday: 1};
const result = {};
Object.keys(_data_set)
.sort((a,b)=> order[a] - order[b])
.forEach(key=> result[key] = _data_set[key]);
console.log(result);
You could use the following:
let new_data_set = {};
for(let item of field_order) {
new_data_set[item] = _data_set[item];
}
This is the sample json:
{
"search": {
"facets": {
"author": [
],
"language": [
{
"value": "nep",
"count": 3
},
{
"value": "urd",
"count": 1
}
],
"source": [
{
"value": "West Bengal State Council of Vocational Education & Training",
"count": 175
}
],
"type": [
{
"value": "text",
"count": 175
}
],
}
}
There are several ways to delete key search.facets.source:
delete search.facets.source
delete jsobObj['search']['facets']['source']
var jsonKey = 'source';
JSON.parse(angular.toJson(jsonObj), function (key, value) {
if (key != jsonKey)
return value;
});
Above 1 & 2 are not dynamic, and 3 is one of the way but not a proper way. Because if source is present in another node then it will not work. Please anybody can tell me how to delete it dynamically in any kind of nested key. Because we can not generate sequence of array dynamically in above 2.
Assuming you're starting from this:
let path = 'search.facets.source';
Then the logic is simple: find the search.facets object, then delete obj['source'] on it.
Step one, divide the path into the initial path and trailing property name:
let keys = path.split('.');
let prop = keys.pop();
Find the facets object in your object:
let parent = keys.reduce((obj, key) => obj[key], jsonObj);
Delete the property:
delete parent[prop];
I have found out another solution, it is very easy.
var jsonKey = 'search.facets.source';
eval('delete jsonObj.' + jsonKey + ';');
I have 2 array objects in Angular JS that I wish to merge (overlap/combine) the matching ones.
For example, the Array 1 is like this:
[
{"id":1,"name":"Adam"},
{"id":2,"name":"Smith"},
{"id":3,"name":"Eve"},
{"id":4,"name":"Gary"},
]
Array 2 is like this:
[
{"id":1,"name":"Adam", "checked":true},
{"id":3,"name":"Eve", "checked":true},
]
I want the resulting array after merging to become this:
[
{"id":1,"name":"Adam", "checked":true},
{"id":2,"name":"Smith"},
{"id":3,"name":"Eve", "checked":true},
{"id":4,"name":"Gary"},
]
Is that possible? I have tried angular's array_merge and array_extend like this:
angular.merge([], $scope.array1, $scope.array2);
angular.extend([], $scope.array1, $scope.array2);
But the above method overlap the first 2 objects in array and doesn't merge them based on matching data. Is having a foreach loop the only solution for this?
Can someone guide me here please?
Not sure if this find of merge is supported by AngularJS. I've made a snippet which does exactly the same:
function merge(array1, array2) {
var ids = [];
var merge_obj = [];
array1.map(function(ele) {
if (!(ids.indexOf(ele.id) > -1)) {
ids.push(ele.id);
merge_obj.push(ele);
}
});
array2.map(function(ele) {
var index = ids.indexOf(ele.id);
if (!( index > -1)) {
ids.push(ele.id);
merge_obj.push(ele);
}else{
merge_obj[index] = ele;
}
});
console.log(merge_obj);
}
var array1 = [{
"id": 1,
"name": "Adam"
}, {
"id": 2,
"name": "Smith"
}, {
"id": 3,
"name": "Eve"
}, {
"id": 4,
"name": "Gary"
}, ]
var array2 = [{
"id": 1,
"name": "Adam",
"checked": true
}, {
"id": 3,
"name": "Eve",
"checked": true
}, ];
merge(array1, array2);
Genuinely, extend in Angular works with object instead of array. But we can do small trick in your case. Here is another solution.
// a1, a2 is your arrays
// This is to convert array to object with key is id and value is the array item itself
var a1_ = a1.reduce(function(obj, value) {
obj[value.id] = value;
return obj;
}, {});
var a2_ = a2.reduce(function(obj, value) {
obj[value.id] = value;
return obj;
}, {});
// Then use extend with those two converted objects
var result = angular.extend([], a1_, a2_).splice(1)
Notes:
For compatibility, reduce may not work.
The after array will replace the previous one. This is because of implementation of extend in Angular.