How can I get unordered array of keys from object - javascript

I have data from backend in my js like this:
var list = {
"6": {
"id": 6,
"name": "John",
"age": 31
},
"42": {
"id": 42,
"name": "Alex",
"age": 25
},
"3": {
"id": 3,
"name": "Tim",
"age": 58
},
};
Then I need to display this data in my angular html template through ngFor directive. But first I have to get an array of object keys:
var listKeys= Object.keys(list);
Next I can output data in template:
<div *ngFor="let item of listKeys">
<p>{{list[item].id}}</p>
<p>{{list[item].name}}</p>
<p>{{list[item].age}}</p>
<hr>
</div>
But the problem is that order of my data changed. I have in listKeys next array ["3", "6", "42"]. But I want to have original order in that one ["6", "42", "3"]. One of solutions that I have found is make keys as not numeric string. For example:
var list = {
"+6": {...},
"+42": {...},
"+3": {...},
};
But I don't have access to backend. I need another solution.
P.S. The way in which I get data from the backend
getData() {
this._dataService.getList(this.name, this.age).subscribe(res => {
this.list = JSON.parse(JSON.stringify(res));
this.listKeys = Object.keys(this.list);
});
}

By definition, an object is an unordered collection of properties. As a solution, you could use an array instead of an object:
The first step would be to convert the response from the server to an array in the same order.
// Original JSON string received from API
var jsonString = `{
"6": {
"id": 6,
"name": "John",
"age": 31
},
"42": {
"id": 42,
"name": "Alex",
"age": 25
},
"3": {
"id": 3,
"name": "Tim",
"age": 58
}
}`;
// Array of ordered id's
const orderedIds = [];
// Find all id's in the JSON string and push them to the array
const pattern = /"?id"?\: (\d*)/g;
let match;
while (match = pattern.exec(jsonString)) {
orderedIds.push(parseInt(match[1]));
}
// parse the original JSON object
const originalList = JSON.parse(jsonString);
// resulting ordered Array
const result = [];
// Push the object in the array by order
for(x of orderedIds) {
result.push(originalList[x]);
}
// Log the resulting array
document.getElementById("result").innerText = JSON.stringify(result);
<pre id="result"></pre>
The result will be an array of the objects in the same order as they appeared in the JSON string:
result = [
{
"id": 6,
"name": "John",
"age": 31
},
{
"id": 42,
"name": "Alex",
"age": 25
},
{
"id": 3,
"name": "Tim",
"age": 58
},
];
After this you can use it in your template:
<div *ngFor="let item of result">
<p>{{item.id}}</p>
<p>{{item.name}}</p>
<p>{{item.age}}</p>
<hr>
</div>
this array does garantee the order of its values.

This is bound to have edge cases, but adding it because it works
If you are getting the data from the backend in the form of JSON then you can do the following
note: var json is a placeholder, as you haven't shown HOW you get your data
var json = `{
"6": {
"id": 6,
"name": "John",
"age": 31
},
"42": {
"id": 42,
"name": "Alex",
"age": 25
},
"3": {
"id": 3,
"name": "Tim",
"age": 58
}
}`;
var result = JSON.parse(json.replace(/\s?"(\d+)":/g, '"$1 ":'));
console.log(Object.keys(result));
Again, this is bound to fail, but I can't see any other way you can "fix" this on the client side - I thought JSON.parse "reviver" function would help, but it gets the properties in 3, 6, 42 order as well - so, no use at all

Related

How to get the duplicates objects in an array?

I have an array like this:
var clients=[{"id":1,"name":"john","age":20},
{"id":3,"name":"dean","age":23},
{"id":12,"name":"harry","age":14},
{"id":1,"name":"sam","age":22},
{"id":13,"name":"Bolivia","age":16},
{"id":7,"name":"sabi","age":60},
{"id":7,"name":"sahra","age":40},
{"id":4,"name":"natie","age":53},{"id":7,"name":"many","age":22}]
I want to find the duplicate objects and cluster them like this:
[
{
"id":1,
"clients":[
{"id":1,"name":"john","age":20},
{"id":1,"name":"sam","age":22}
]
},
{
"id":7,
"clients":[
{"id":7,"name":"sabi","age":60},
{"id":7,"name":"sahra","age":40},
{"id":7,"name":"many","age":22}
]
}
]
can I do that with filter() like this:clients.reduce(//code hier)?
reduce() is tailor made for this. When you want to aggregate over an array and get a computed result, you should use reduce().
find() is another array method, which helps in finding an array element based on a condition (here the matching of id property).
var clients=[{"id":1,"name":"john","age":20},
{"id":3,"name":"dean","age":23},
{"id":12,"name":"harry","age":14},
{"id":1,"name":"sam","age":22},
{"id":13,"name":"Bolivia","age":16},
{"id":7,"name":"sabi","age":60},
{"id":7,"name":"sahra","age":40},
{"id":4,"name":"natie","age":53},{"id":7,"name":"many","age":22}]
let ans = clients.reduce((agg,x,index) => {
let findI = agg.find( a =>
a.id === x.id
);
if(findI) findI.clients.push(x);
else {
agg.push({
id : x.id,
clients : [x]
});
}
return agg;
},[]);
console.log(ans);
The simplest solution would be to loop over the clients and check for an existing object with the same id. If yes, push to clients array. Or else, just create one.
var clients = [{ "id": 1, "name": "john", "age": 20 },
{ "id": 3, "name": "dean", "age": 23 },
{ "id": 12, "name": "harry", "age": 14 },
{ "id": 1, "name": "sam", "age": 22 },
{ "id": 13, "name": "olivia", "age": 16 },
{ "id": 7, "name": "sabi", "age": 60 },
{ "id": 7, "name": "sahra", "age": 40 },
{ "id": 4, "name": "natie", "age": 53 }, { "id": 7, "name": "kany", "age": 22 }]
const groups = [];
for (let client of clients) {
const existingGroup = groups.find(group => group.id == client.id)
if (existingGroup)
existingGroup.clients.push(client);
else {
groups.push({ id: client.id, clients: [client] });
}
}
console.log(groups);
You can reassign the original object with the temporary object just used for this, and continue with your business logic, which I believe is the one you are looking for.

How to read JSON using javascript?

I have JSON data like this -
var json = {
"details": [
{
"A": {
"Name": "mike",
"Age": 22
},
"B": {
"Name": "John",
"Age": 25
}
}
]
}
I want to read A,B points as an array.
Another way to do it with your json, Object.keys(),since your options are not in array form, can use that to convert to array form.
var json = {
"details": [
{
"A": {
"Name": "mike",
"Age": 22
},
"B": {
"Name": "John",
"Age": 25
}
}
]
}
var outputDiv = document.getElementById('output');
var options = Object.keys(json.details[0]).map(function(item){
return '<option value="'+item+'">'+ item +'</option>'
})
options.unshift('<option value="" > Please select </option>')
var select = document.getElementById('your_options');
select.innerHTML = options.join()
select.onchange = function() {
outputDiv.innerHTML = JSON.stringify(json.details[0][this.value]);
}
<label>You options</label>
<select id="your_options">
</select>
<div id="output"></div>
Lets assume you receive the following JSON from a web server
'{ "firstName":"Foo", "lastName":"Bar" }'
To access this data you first need to parse the raw JSON and form a Javascript object
let response = JSON.parse('{ "firstName":"Foo", "lastName":"Bar" }');
This forms an object which we can access relativly simply
let firstName = response["firstName"];
let lastName = response["lastName"];
Have a look at javascript documentation regarding JSON:
http://devdocs.io/javascript-json/
Examples:
JSON.parse('{}'); // {}
JSON.parse('true'); // true
JSON.parse('"foo"'); // "foo"
JSON.parse('[1, 5, "false"]'); // [1, 5, "false"]
JSON.parse('null'); // null

Access nested members in JSON

I'm trying to access members in a json, however I am running into some trouble. Here is an example of one of the json objects, stored in var obj:
var fs = require('fs');
var obj = [
{
"_id": "52d7f816f96d7f6f31fbb680",
"regNum": "0361300035313000002",
"sd": "2013-01-01T00:00:00",
"pd": "2013-01-25T09:30:29Z",
"prd": "2012-12-18",
"p": 1395000000,
"pt": [
{
"name": name here",
"price": 1395000000,
"OKDP": {
"code": "5520109",
"name": "name here"
},
"sid": "25484812",
"sum": "1395000000",
"OKEI": {
"code": "796",
"name": "name two"
},
"quantity": "1"
}
],
"b": 0,
"c": 0,
"s": 0
}
];
I'm trying to access the sid and sum values, by doing the following:
var sid = [];
var sum = [];
obj.forEach(block => {
var sidOut = block.pt.sid;
var sumOut = block.pt.sum;
sid.push(sidOut);
sum.push(sumOut);
});
console.log(sid);
console.log(sum);
I tried the solution here, however, when I run these it gives me [ undefined ] errors.
Why am I unable to access this two values?
if you see your pt is an array of an object [{}] so you need to select which element you want to access so
var sidOut = block.pt[0].sid;
var sumOut = block.pt[0].sum;
should get you the right result

AngularJS search filter in array into object

I look ID in an array of objects JSON.
Example JSON:
{
"Przydzial": [{
"M": "Cos",
"Przydzialt": [{
"Name": "",
"Przydz": "tach_1",
"Cos": "Pod",
"Ha": "20",
"ID": "94"
}, {
"Name": "B_K",
"Przydz": "lea",
"Cos": "Chea",
"HA": "8",
"ID": "78"
}
}]
}]
}
Use in controller
var foo = { //my json };
var nowy = $filter('filter')(foo.Przydzialt, { ID:78});
result:
console.log(nowy); // undefined
json is correct - validated in JSLint.
As "$foo.Przydzial" is an array of objects, where every object has its "Przydzialt" attribute, you should execute $filter in a loop:
var newArray;
angular.forEach($foo.Przydzial, function (el) {
newArray = $filter('filter')(el.Przydzialt, {ID: 78});
console.log(newArray);
});

Is this valid json data?

The url has following json data:
[{ "topic": "cricket",
"value": "Player [ playerid=123, category=b, high=150, total=2300]",
"place": "xyz"},
{ "topic": "cricket",
"value": "Player [ playerid=456, category=c, high=60, total=300]",
"place": "abc"},
{ "topic": "cricket",
"value": "Player [ playerid=789, category=a, high=178, total=5300]",
"place": "bnm"}]
I tried online to check whether this is valid json or not through following link: http://jsonformatter.curiousconcept.com/ it says valid. if it is, how do I access each playerid ?
It is valid JSON, but the data about the player is embedded in a random string. You can do one of two things:
Update the service to send back a different, valid JS value, for example:
"value": {
"type": "Player",
"playerid": 123,
"category": "b",
"high": 150,
"total": 2300
}
Parse the data in the value key yourself:
// Simple regex, not really "parsing"
var playerIdRE = /playerid=(\d+)/i;
var result = playerIdRE.exec(yourData[0].value);
// result[0] is the full match, while result[1] is the ID.
// Or the more complicated version that does full parsing
var format = /\s*(.*?)\s*\[\s*([^\]]+)\s*\]\s*/gi,
keyValuePair = /(\w+)=([^,\]]*),?\s*/gi
function parseComplexDataType(input) {
var result = format.exec(input),
typeName = result[1],
keyValues = result[2],
returnValue = {};
if (!typeName) return returnValue;
returnValue.typeName = typeName;
input.replace(keyValuePair, function(_, key, value) {
returnValue[key] = value;
});
return returnValue;
}
// Usage:
> parseComplexDataType("Player [ playerid=123, category=b, high=150, total=2300]")
Object {typeName: "Player", playerid: "123", category: "b", high: "150", total: "2300"}
For your purposes, it is not valid. Once the JSON is corrected, you simply need to loop through the array and read each value.
var jArray = [{
"topic": "cricket",
"value": {
"type": "Player",
"playerid": 123,
"category": "b",
"high": 150,
"total": 2300
},
"place": "xyz"
}, {
...
}]
To access the JSON data ...
for (var i=0,len=jArray.length; i<len; i++) {
console.log(jArray[i].topic, jArray[i].value.type);
}
Yes, it is. I check it via: http://jsonlint.com/
Extracting "playerid":
Initialise the string to JSONArray.
Iterate over each element in the above array.
Now, from each element extract "value".
Finally, from this string you can get "playerid" by using string methods (see the code below).
Below is the code in Java:
ArrayList<String> player_ids = new ArrayList<String>();
String s = "YOUR STRING";
JSONArray ja = new JSONArray(s);
for(int i =0; i<ja.length(); i++)
{
String value = ja.getJSONObject(i).getString("value");
int start = value.indexOf("=");
int end = value.indexOf(",");
String player_id = value.substring(start+1, end);
player_ids.add(player_id);
}
Hope it helps!!

Categories

Resources