This question already has answers here:
How can I remove a specific item from an array in JavaScript?
(142 answers)
Closed 5 years ago.
This Object:
var Betreiber = {
"user1": [
{
"desc": "60",
"Id": 3473631702,
"Status": "offline"
},
{
"desc": "61",
"Id": 3473631703,
"Status": "offline"
}
],
"user2": [
{
"desc": "62",
"Id": 963346121,
"Status": "offline"
},
{
"desc": "63",
"Id": 963346122,
"Status": "offline"
}
],
"user3": [
{
"desc": "64",
"Id": 972878784
},
{
"desc": "65",
"Id": 3473631706,
"Status": "offline"
}
]
}
My code:
var anlagen = [963346121, 963346122];
for(var users in Betreiber) {
for(var k=0;k<anlagen.length; k++) {
for(var ids in Betreiber[users]) {
if(anlagen[k] != Betreiber[users][ids].Id ){
delete Betreiber[users][ids];
}
}
}
if(Betreiber[users].length === 0) {
delete Betreiber[users];
}
}
i want to splice / delete every Element that doesn't fit my anlagen Array.
For some reason, the Elements are removed, but not completely deleted.
For Example: If i only want to keep the values of user1:
State: user1: [ , ], user2: [ , ], user3: [ , ]
Desired: user1: [data....]
If the user.length is 0, i wan't to delete the whole user.
I think this is what you want:
var Betreiber = {
"user1": [{
"desc": "60",
"Id": 3473631702,
"Status": "offline"
},
{
"desc": "61",
"Id": 3473631703,
"Status": "offline"
}
],
"user2": [{
"desc": "62",
"Id": 963346121,
"Status": "offline"
},
{
"desc": "63",
"Id": 963346122,
"Status": "offline"
}
],
"user3": [{
"desc": "64",
"Id": 972878784
},
{
"desc": "65",
"Id": 3473631706,
"Status": "offline"
}
]
};
var anlagen = [963346121, 963346122];
Object.keys(Betreiber).forEach(key => {
Betreiber[key] = Betreiber[key].filter(item => {
return anlagen.indexOf(item.Id) !== -1;
});
if(!Betreiber[key].length) {
delete Betreiber[key];
}
});
console.log(Betreiber);
You can just filter the element out which don't meet your criteria using Array#filter. And if the resultant array is of length 0, you can delete its key from the object.
var anlagen = [963346121, 963346122];
for(var user in Betreiber) {
for (var k = 0, len = anlagen.length; k < len; k++) {
for (var j = 0, _len = Betreiber[user].length; j < _len; j++) {
if (anlagen[k] != Betreiber[user][j].Id ) {
Betreiber[user].splice(j, 1);
}
}
}
if (Betreiber[user].length === 0) {
delete Betreiber[user];
}
}
Related
This is a nested json file and I am trying to arrange it in a readable format to display in a table
I tried to manually put all the keys and values with in a for loop but there should be an elegant way to achieve this and hence I am reaching SO.
The actual JSON is quite a nested one and needed time to execute data with 500k rows
The result should be enhanced JSON with parent values appearing for child values as well
var property = {
"data": [{
"ID": "123456",
"name": "Coleridge st",
"criteria": [
{
"type": "type1",
"name": "name1",
"value": "7",
"properties": []
},
{
"type": "type2",
"name": "name2",
"value": "6",
"properties": [
{
"type": "MAX",
"name": "one",
"value": "100"
}, {
"type": "MIN",
"name": "five",
"value": "5"
}
]
},
{
"type": "type3",
"name": "name3",
"value": "5",
"properties": [{
"type": "MAX1",
"name": "one6",
"value": "1006"
}, {
"type": "MIN2",
"name": "five6",
"value": "56"
}]
}
]
},
{
"ID": "456789",
"name": "New Jersy",
"criteria": [
{
"type": "type4",
"name": "name4",
"value": "6",
"properties": [{
"type": "MAX12",
"name": "one12",
"value": "10012"
}, {
"type": "MIN23",
"name": "five12",
"value": "532"
}]
}
]
}]
};
var output = [];
property.data.forEach(function (users) {
var multirows = {
id: users.ID,
name: users.name,
};
for (var i = 0; i < users.criteria.length; i++) {
var criterias = {
type: users.criteria[i].type,
name: users.criteria[i].name,
value: users.criteria[i].value,
}
var mat_contacts_rows;
if (!isEmpty(users.criteria[i].properties)) {
for (var j = 0; j < users.criteria[i].properties.length; j++) {
var property = {
type: users.criteria[i].properties[j].type,
name: users.criteria[i].properties[j].name,
value: users.criteria[i].properties[j].value
};
mat_contacts_rows = { ...multirows, ...{ criteria: criterias }, ...{ properties: property } };
output.push(mat_contacts_rows);
}
} else {
var property = [];
mat_contacts_rows = { ...multirows, ...{ criteria: criterias }, ...{ properties: property } };
output.push(mat_contacts_rows);
}
}
});
console.log(JSON.stringify(output, undefined, 2))
function isEmpty(obj) {
for (var key in obj) {
if (obj.hasOwnProperty(key))
return false;
}
return true;
}
I think this could be a great exercise to you to don't answer your question but to give you some tips. You should first look at : Lodash wish has a bunch of usefull method to help you doing what you'r trying to do.
In a second time you should avoir using .forEach or for loops and try using Array.prototype.map or Array.prototype.reduce
I'm stuck with something I thought would be easy. Let's say I have an object like this. I'm trying to insert in the div each name of the animal tagged and the number of times that tag is in types (for example, cat = 3, etc...)
var animals = '';
animals = {
"types": [
{
"id": "1",
"tags": ["cat"]
},
{
"id": "2",
"tags": ["dog"]
},
{
"id": "3",
"tags": ["cat", "bird", "dog"]
},
{
"id": "4",
"tags": []
},
{
"id": "5",
"tags": ["cat", "bird"]
}
]
}
for (var i = 0; i < animals.length; i++) {
var tags = animals[i].tags;
}
<div class="types">Number of animals:</div>
I'm a beginner with complex JSON objects, any help would be appreciated. It can be vanilla JS or Jquery.
Thanks!
Check out the snippet below, first loop iterates and counts each animal.
Second populates your div
var animals = '';
animals = {
"types": [{
"id": "1",
"tags": ["cat"]
},
{
"id": "2",
"tags": ["dog"]
},
{
"id": "3",
"tags": ["cat", "bird", "dog"]
},
{
"id": "4",
"tags": []
},
{
"id": "5",
"tags": ["cat", "bird"]
}
]
}
var tags = {};
// Iterate over all your items
animals.types.forEach(function(type) {
// Iterate over all the animals in the array
type.tags.forEach(function(tag) {
if (tag in tags) {
// If animal is present, increment the count
tags[tag] = tags[tag] + 1;
} else {
// If animal is not present, add the entry
tags[tag] = 1;
}
})
})
// Iterate over all the animals and add it to the div
for (var animal in tags) {
if (tags.hasOwnProperty(animal)) {
document.getElementsByClassName('types')[0].innerHTML += ' ' + animal + ' ' + tags[animal];
}
}
<div class="types">Number of animals:</div>
You can do like this by using map() method :
var animals = {
"types": [{
"id": "1",
"tags": ["cat"]
},
{
"id": "2",
"tags": ["dog"]
},
{
"id": "3",
"tags": ["cat", "bird", "dog"]
},
{
"id": "4",
"tags": []
},
{
"id": "5",
"tags": ["cat", "bird"]
}
]
};
var count = {};
animals.types.map(function (arr, i) {
arr.tags.map(function (tag, k) {
count[tag] = (count[tag] || 0) + 1;
});
});
console.log(count);
If you use reduce & destrucuring it becomes one liner:
var animals = {
"types": [{
"id": "1",
"tags": ["cat"]
},
{
"id": "2",
"tags": ["dog"]
},
{
"id": "3",
"tags": ["cat", "bird", "dog"]
},
{
"id": "4",
"tags": []
},
{
"id": "5",
"tags": ["cat", "bird"]
}
]
}
console.log(
animals.types.reduce((r,{tags}) => tags.map(tag => r[tag] = (r[tag] || 0) + 1) && r, {})
)
Try this simple way:
var animals = { "types": [ { "id": "1", "tags": ["cat"] }, { "id": "2", "tags": ["dog"] }, { "id": "3", "tags": ["cat", "bird", "dog"] }, { "id": "4", "tags": [] }, { "id": "5", "tags": ["cat", "bird"] } ] }
var finalRes={};
animals.types.map(function(o, i){
o.tags.map(function(p, j){
finalRes[p]=(finalRes[p]||0)+1;
});
});
console.log(finalRes);
Result:
{ cat: 3, dog: 2, bird: 2 }
Sorry, I am typing with mobile phone, slow but correct!
Flatten all tags into single array
Count each tag
Handle tag count as you need
const animals = {
"types": [
{
"id": "1",
"tags": ["cat"]
},
{
"id": "2",
"tags": ["dog"]
},
{
"id": "3",
"tags": ["cat", "bird", "dog"]
},
{
"id": "4",
"tags": []
},
{
"id": "5",
"tags": ["cat", "bird"]
},
],
};
// Flatten all tags into single array
var allTags = [].concat(
...animals.types.map(
(type) => type.tags
)
);
// Count each tag
const tagsCount = {};
allTags.forEach(
(tag) => tagsCount[tag] = tagsCount[tag] ? tagsCount[tag] + 1 : 1
)
// Handle tag count as you need
const app = document.querySelector('#app');
app.innerHTML = Object.keys(tagsCount).map((key) => {
return `<p>${key}: ${tagsCount[key]}</p>`
}).join('');
<h1>Number of Animal Types</h1>
<div id="app"></div>
Basic javascript usage.
// var animals = ''; // not needed
var animals = {
"types": [{
"id": "1",
"tags": ["cat"]
},
{
"id": "2",
"tags": ["dog"]
},
{
"id": "3",
"tags": ["cat", "bird", "dog"]
},
{
"id": "4",
"tags": []
},
{
"id": "5",
"tags": ["cat", "bird"]
}
]
};
var counts = {};
for (var i = 0; i < animals.types.length; i++) { // types is a key in animals object, animals is not an array
var tags = animals.types[i].tags;
if (tags.length > 0) {
for (var j = 0; j < tags.length; j++) {
var tag = tags[j];
if (typeof counts[tag] === 'undefined') {
counts[tag] = 0;
}
counts[tag]++;
}
}
}
console.log(counts);
You could create a hash map for all the tags and increment the count whenever you encounter that tag in that types.tags array
Then loop through the object and append that into your HTML Element
var animals = '';
animals = {
"types": [
{
"id": "1",
"tags": ["cat"]
},
{
"id": "2",
"tags": ["dog"]
},
{
"id": "3",
"tags": ["cat", "bird", "dog"]
},
{
"id": "4",
"tags": []
},
{
"id": "5",
"tags": ["cat", "bird"]
}
]
}
let types = animals.types;
var counts = {};
for (var i = 0; i < types.length; i++) {
types[i].tags.forEach((x) => {
counts[x] = (counts[x] || 0)+1;
});
}
console.log(counts);
<div class="types">Number of animals:</div>
This question already has answers here:
Find by key deep in a nested array
(21 answers)
Closed 4 years ago.
I have a Javascript object with lots of different sections. How can I search through all of the sections to find the position of a specific ID? The ID's that I am searching for are not in a specific location, and can be located in any of the tree branches.
For example, I am searching for this ID:
xobmnbjxg0g_1527269346261
And I am trying to output the position of that ID, which would be this:
app['structure'][0]['if-children'][0]['id']
My Javascript Object:
var app = {
"structure": [
{
"id": "0",
"type":"IF",
"parameters": [
{
"id": "xobmnbjxg0g_1527269346260",
"type": "field",
"value": "CV_TEST_SPOT1X"
},
{
"id": "2",
"type": "operator",
"value": "="
},
{
"id": "3",
"type": "field",
"value": "North America"
}
],
"if-children": [
{
"id": "xobmnbjxg0g_1527269346261",
"type":"IF",
"parameters": [
{
"id": "1",
"type": "field",
"value": "CV_TEST_SPOT1"
},
{
"id": "2",
"type": "operator",
"value": "="
},
{
"id": "3",
"type": "field",
"value": "North America"
}
],
"if-children":[
],
"else-children":[
]
}
],
"else-children":[
{
"id": "xobmnbjxg0g_1527269346262",
"type":"IF",
"parameters": [
{
"id": "1",
"type": "field",
"value": "CV_TEST_SPOT1"
},
{
"id": "2",
"type": "operator",
"value": "="
},
{
"id": "3",
"type": "field",
"value": "North America"
}
],
"if-children":[
{
"id":"xobmnbjxg0g_152726934626X"
}
],
"else-children":[
{
"id":"xobmnbjxg0g_152726934626Y"
}
]
}
]
},
{
"id": "xobmnbjxg0g_1527269346263",
"type":"IF",
"parameters": [
[
{
"id": "1",
"type": "field",
"value": "CV_TEST_SPOT1"
}
]
],
"if-children": [
{
"id": "xobmnbjxg0g_1527269346264",
"type":"IF",
"parameters": [
[
{
"id": "1",
"type": "field",
"value": "CV_TEST_SPOT1"
}
]
],
"if-children":[
{
"id": "xobmnbjxg0g_1527269346265",
"type":"IF",
"parameters": [
{
"id": "1",
"type": "field",
"value": "CV_TEST_SPOT1"
}
],
"if-children":[
{
"id":"xobmnbjxg0g_1527269346266"
}
],
"else-children":[
{
"id":"xobmnbjxg0g_1527269346267"
}
]
}
],
"else-children":[
{
"id":"xobmnbjxg0g_1527269346268"
}
]
}
],
"else-children":[
{
"id":"xobmnbjxg0g_1527269346269"
}
]
}
]
};
Interesting puzzle/question.
pretty sure there are some edge cases im missing but this seems to pass some tests.
function is(obj, type){
return Object.prototype.toString.call(obj) === `[object ${type}]`;
}
function findPosition(obj, mykey, myval, res){
if(is(obj, "Object")){
if(mykey in obj && obj[mykey] === myval){
res.tree.push(mykey);
res.found = true;
} else {
for( let key in obj){
if(res.found) break;
res.tree.push(key);
findPosition(obj[key], mykey, myval, res);
}
if(!res.found) res.tree.pop();
}
} else if(is(obj, "Array")){
for(let i = 0; i < obj.length; i++){
if(res.found) break;
res.tree.push(i);
findPosition(obj[i], mykey, myval, res);
}
if(!res.found) res.tree.pop();
} else {
res.tree.pop();
}
return res;
}
Usage and output
findPosition([{one: { two: [{id: [{id:'my'}]}]}}], "id", "mys", {tree:[], found: false})
> tree: Array(0), found: false}
findPosition([{one: { two: [{id: [{id:'my'}]}]}}], "id", "my", {tree:[], found: false})
> {found: true, tree: [0, "one", "two", 0, "id", 0, "id"]}
For finding if current obj you are iterating over is an Array you can also use Array.isArray
I'm having this Object/Array Structure :
Obj = {
"User": {
"user1": [{
"desc": "NG60",
"Id": 3473631702,
"Status": "offline"
}],
"user2": [{
"desc": "somevalue",
"Id": 963346121,
"Status": "offline"
},
{
"desc": "othervalue", // SPLICE THIS OUT
"Id": 963346122, // SPLICE THIS OUT
"Status": "offline" // SPLICE THIS OUT
}],
"user3": [{
"desc": "whatever",
"Id": 972878784
}]
}
}
I want to filter out different values, dynamically (fixed in this example)
and if there are no Ids left, I want to delete the whole user Array.
For example, if I want to filter out the 2nd Array Element of user2:
for(var users in Obj) {
for(var Ids in Obj[users]) {
if(Obj[users][Ids].Id == 963346122){
Obj[users][Ids].splice(0, 1); // ERROR HERE
}
}
if(Obj[users][Ids] == undefined) {
delete Obj[users];
}
}
I get this Error:
User[users][Ids].splice(0, 1) is not a function
How to splice only the Array Element that I'm addressing, not the complete user2 Array?
Use array.prototye.filter to remove user from array and use delete to remove the whole user array in case there is no element left:
var obj = {
"User": {
"user1": [
{
"desc": "NG60",
"Id": 3473631702,
"Status": "offline"
}
],
"user2": [
{
"desc": "somevalue",
"Id": 963346121,
"Status": "offline"
},
{
"desc": "othervalue", // SPLICE THIS OUT
"Id": 963346122, // SPLICE THIS OUT
"Status": "offline" // SPLICE THIS OUT
}
],
"user3": [
{
"desc": "whatever",
"Id": 972878784
}
]
}
};
function deleteUser(id) {
Object.keys(obj.User).forEach(user => {
obj.User[user] = obj.User[user].filter(u => u.Id !== id);
if (obj.User[user].length === 0) {
delete obj.User[user];
}
});
}
deleteUser(963346121);
console.log(obj);
deleteUser(972878784);
console.log(obj);
You have to use another for loop to wrap the actual operation because the length is not the same for all iterating objects. That's why you have to slice the object from the proper position.
Try the following:
let Obj = {
"User": {
"user1": [
{
"desc": "NG60",
"Id": 3473631702,
"Status": "offline"
}
],
"user2": [
{
"desc": "somevalue",
"Id": 963346121,
"Status": "offline"
},
{
"desc": "othervalue", // SPLICE THIS OUT
"Id": 963346122, // SPLICE THIS OUT
"Status": "offline" // SPLICE THIS OUT
}
],
"user3": [
{
"desc": "whatever",
"Id": 972878784
}
]
}
}
for(var users in Obj) {
for(var Ids in Obj[users]) {
for(var i=0; i<Obj[users][Ids].length;i++){
if(Obj[users][Ids][i].Id == 963346122){
Obj[users][Ids].splice(i, 1); // ERROR HERE
}
}
}
if(Obj[users][Ids] == undefined) {
delete Obj[users];
}
}
console.log(Obj);
Problem: the splice you used was pointing to string not Object/Array. Use delete rather than splice for Object removal.
Better for future filters:
//using same Obj:
for (i in Obj) {
if (Obj.hasOwnProperty(i)) {
var subObj = Obj[i];
for (j in subObj) {
var child = subObj[j];
for (k in subObj[j]) {
if(child[k].Id == 963346122){ //this user contains specified id the delete this user.
delete child[k];
}
}
}
}
}
In javascript/jquery how do i achieve following
old_dataset = [
{
"dob": "xyz",
"name": {
"first": " abc",
"last": "lastname"
},
"start_date": {
"moth": "2",
"day": "5",
"year": 1
},
"children": [
{
"child": {
"id": "1",
"desc": "first child"
}
},
{
"child": {
"id": "2",
"desc": "second child"
}
}
]
},
{
"dob": "er",
"name": {
"first": " abc",
"last": "txt"
},
"start_date": {
"moth": "2",
"day": "5",
"year": 1
},
"children": [
{
"child": {
"id": "1",
"desc": "first child"
}
},
{
"child": {
"id": "2",
"desc": "second child"
}
}
]
}
]
Using jquery iterate over the above and change to following
new_dataset = [
{
"dob":"xyz",
"name": <first and last name values>
"start_date":<value of month day year>,
"children": [ {
child_id :1,
child_id : 2
},
]
},{
"dob":"er",
"name": <first and last name values>
"start_date":<value of month day year>,
"children": [ {
child_id :1,
child_id : 2
},
]
}]
If someone can give the code to transform the data it would help me to understand the iteration
You could do something like:
function transformDataset(oldDataset) {
var newDataset = [];
var newObj;
for (var i = 0; i < oldDataset.length; i++) {
newObj = transformObj(oldDataset[i]);
newDataset.push(newObj);
}
return newDataset;
}
function transformObj(obj) {
var children = obj.children;
obj.name = obj.name.first + ' ' + obj.name.last;
obj.start_date = obj.start_date.month + ' ' + obj.start_date.day + ' ' + obj.start_date.year;
obj.children = [];
for (var i = 0; i < children.length; i++) {
obj.children.push(children[i].child.id);
}
return obj;
}
var new_dataset = transformDataset(old_dataset);
Note that new_dataset will have an array of child id instead of an object with multiple child_id properties.
You also had a typo in old_dataset.start_date.month (was written moth)(or maybe that was intentional).
use map first to iterate the array data (old_dataset), replace element name & start_date with new value then return the array
const old_dataset = [
{
"dob": "xyz",
"name": {
"first": " abc",
"last": "lastname"
},
"start_date": {
"moth": "2",
"day": "5",
"year": 1
},
"children": [
{
"child": {
"id": "1",
"desc": "first child"
}
},
{
"child": {
"id": "2",
"desc": "second child"
}
}
]
},
{
"dob": "er",
"name": {
"first": " abc",
"last": "txt"
},
"start_date": {
"moth": "2",
"day": "5",
"year": 1
},
"children": [
{
"child": {
"id": "1",
"desc": "first child"
}
},
{
"child": {
"id": "2",
"desc": "second child"
}
}
]
}
]
let new_dataset = old_dataset.map((arr) => {
arr.name = `${arr.name.first} ${arr.name.last}`
arr.start_date = `${arr.start_date.moth} ${arr.start_date.day} ${arr.start_date.year}`
return arr
})
console.log(new_dataset)