I have one JSON Object like this :
var myObject = [
{
"Name" : "app1",
"id" : "1",
"groups" : [
{ "id" : "test1",
"name" : "test group 1",
"desc" : "this is a test group"
},
{ "id" : "test2",
"name" : "test group 2",
"desc" : "this is another test group"
}
]
},
{
"Name" : "app2",
"id" : "2",
"groups" : [
{ "id" : "test3",
"name" : "test group 4",
"desc" : "this is a test group"
},
{ "id" : "test4",
"name" : "test group 4",
"desc" : "this is another test group"
}
]
},
{
"Name" : "app3",
"id" : "3",
"groups" : [
{ "id" : "test5",
"name" : "test group 5",
"desc" : "this is a test group"
},
{ "id" : "test6",
"name" : "test group 6",
"desc" : "this is another test group"
}
]
}
];
I have new value available of "name" for specific "id".
How can I replace "name" of specific "id" inside any object ?
And how to count total number of groups among all objects ?
for example : replace name to "test grp45" for id = "test1"
Here is fiddle
http://jsfiddle.net/qLTB7/21/
The following function will search through an object and all of its child objects/arrays, and replace the key with the new value. It will apply globally, so it won't stop after the first replacement. Uncomment the commented line to make it that way.
function findAndReplace(object, value, replacevalue) {
for (var x in object) {
if (object.hasOwnProperty(x)) {
if (typeof object[x] == 'object') {
findAndReplace(object[x], value, replacevalue);
}
if (object[x] == value) {
object["name"] = replacevalue;
// break; // uncomment to stop after first replacement
}
}
}
}
Working jsfiddle: http://jsfiddle.net/qLTB7/28/
Try this
function findAndReplace(object,keyvalue, name) {
object.map(function (a) {
if (a.groups[0].id == keyvalue) {
a.groups[0].name = name
}
})
}
findAndReplace(myObject,"test1" ,"test grp45");
Here's a different approach using Array.prototype.some. It assumes that the Name property in the outer objects should be actually be name (note capitalisation).
function updateNameById(obj, id, value) {
Object.keys(obj).some(function(key) {
if (obj[key].id == id) {
obj[key].name = value;
return true; // Stops looping
}
// Recurse over lower objects
else if (obj[key].groups) {
return updateNameById(obj[key].groups, id, value);
}
})
}
The advantage of some is that it stops as soon as the callback returns true.
I think this should work for you:-
var id = 'test1';
var newname = 'test grp45';
var numberOfGruops = 0;
myObject.forEach(function(app){
numberOfGruops += app.groups.length; //Count all groups in this app
app.groups.forEach(function(group){
if(group.id===id)
group.name = newname; // replace the name
});
});
Maybe a more succinct sol'n
function changeName(objArray, objId, newName) {
objArray.forEach(function(obj) {
if (obj.id === objId) obj.Name = newName;
});
}
Personally: if this were me, when creating these objects, I would create a new obj and key them by id.
var myApps = {};
myObject.forEach(function(o) {
myApps[o.id] = o;
});
=>
{
"1": {
"Name": "app1",
"id": "1",
"groups": [
{
"id": "test1",
"name": "test group 1",
"desc": "this is a test group"
},
{
"id": "test2",
"name": "test group 2",
"desc": "this is another test group"
}
]
}
}
And then you could just do:
myApps['someId'].name = 'This is my new Name'
Check it out here:
http://jsfiddle.net/qLTB7/40/
it should be if (object["id"] == value) instead of if (object[x] == value) in 7th line of PitaJ answer, so whole function will look like:
function findAndReplace(object, value, replacevalue) {
for (var x in object) {
if (object.hasOwnProperty(x)) {
if (typeof object[x] == 'object') {
findAndReplace(object[x], value, replacevalue);
}
if (object["id"] == value) {
object["name"] = replacevalue;
// break; // uncomment to stop after first replacement
}
}
}
}
if you leave object[x] - function will replace name also for objects with other keys values set to "test1", for example
{"id": "xxx", "name": "test group 1", "desc": "test1"}
Related
I have some JSON that looks like this
var js = '{
"person" : {
"firstname" : "Steve",
"lastname" : "Smith",
"other": [
{
"age" : "32",
"deceased" : false
},
{
"age" : "14",
"deceased" : false
},
{
"age" : "421",
"deceased" : false
}
]
}
}'
I know how I delete all of "other" by doing this
var j = JSON.parse(js)
delete j[person.other]
but what I really want is to delete the "other" node with a condition that is age = 14.
The result JSON I am looking for is
{
"person" : {
"firstname" : "Steve",
"lastname" : "Smith",
"other": [
{
"age" : "32",
"deceased" : false
},
{
"age" : "421",
"deceased" : false
}
]
}
}
I have looked at the delete operator here and it does not provide a conditional.
Sorry if this is too simple a question. I am learning.
Thanks
The best approach to this would be not to alter the json, but create another one instead:
const filtered = { ...json, other: json.other.filter(item => item.age !== "14") }
If you really need to alter the json, you can do the following:
let index = json.other.findIndex(item => item.age === "14")
while (index !== -1) {
json.other.splice(index, 1)
index = json.other.findIndex(item => item.age === "14")
}
You can use a filter on the array doing something like
j[person.other].filter(x => x.age != 14)
Doc on how filter works more in depth here :
https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
I have two objects
var JSON_Categories = '[{ "id" : "1", "text" : "Category A"}, { "id" : 2, "text" : "Category B" }]';
var JSON_Article = '[{ "id" : "1", "text" : "Article text A"}, { "id" : 3, "text" : "Article B"}]';
var categories = JSON.parse(JSON_Categories);
var article = JSON.parse(JSON_Article);
if id match for both JSON value then, I need to assign text category text value with an article text value.
it tried something like this, I know it's not a good solution can anyone help me on it?
var categoryValue = new Object();
categories.forEach(function(category) {
articles.forEach(article => {
if (category.id === article.id) {
categoryValue.id = category.id;
categoryValue.text = article.text;
} else {
categoryValue.id = category.id;
categoryValue.text = category.text;
}
});
});
console.log('categoryValue', categoryValue);
You can map it and inside that find the Object from second array:
var JSON_Categories = JSON.parse('[{ "id" : "1", "text" : "Category A"}, { "id" : 2, "text" : "Category B" }]');
var JSON_Article = JSON.parse('[{ "id" : "1", "text" : "Article text A"}, { "id" : 3, "text" : "Article B"}]');
var result = JSON_Categories.map(({id, text})=>({id, text:JSON_Article.find(k=>k.id==id)?.text || text}));
console.log(result);
I have a list of objects. On each object I have an array.
Example:
"-KpvPH2_SDssxZ573OvM" : {
"date" : "2017-07-25T20:21:13.572Z",
"description" : "Test",
"id" : [ {
0: "0a477fed-8944-9f5d-56fd-c95fe7663a07",
1: "0a477fed-8944-9f5d-56fd-c95fe7663a08"
} ]
},
"-KpvPLSfotrZiBDeVOxU" : {
"date" : "2017-07-25T20:21:33.159Z",
"description" : "Test 2",
"id" : [ {
0: "6e79eadd-21b5-91cc-4b71-7ac1a42278b1"
} ]
}
How do I search for an object using the ID array as a parameter?
When I need to filter only one array I use filter and everything works ok.
var result = $.grep(items, function(e){ return e.id == id; });
But in this case I believe it does not work.
Thanks
Since the ID's are a little deeper in the object, and they are part of an object, I think a better approach (as compared to $.grep) would be a custom filter. Here I have assumed you want exact comparison while filtering, based on your question. But you could easily have partial comparison with indexOf as well.
var data = {
"-KpvPH2_SDssxZ573OvM": {
"date": "2017-07-25T20:21:13.572Z",
"description": "Test",
"id": [{
0: "0a477fed-8944-9f5d-56fd-c95fe7663a07",
1: "0a477fed-8944-9f5d-56fd-c95fe7663a08"
}]
},
"-KpvPLSfotrZiBDeVOxU": {
"date": "2017-07-25T20:21:33.159Z",
"description": "Test 2",
"id": [{
0: "6e79eadd-21b5-91cc-4b71-7ac1a42278b1"
}]
}
};
//console.log(data);
var inputID = "0a477fed-8944-9f5d-56fd-c95fe7663a08";
var filteredData = [];
for (var prop in data) {
if(data.hasOwnProperty(prop)) {
var item = data[prop];
var itemIDs = item.id[0];
for(var id in itemIDs) {
if (itemIDs[id] == inputID) {
filteredData.push(item);
}
}
}
}
console.log(filteredData);
I have looked at Display partial array value matches from user input and tried to achieve the same results.
The difference is the array format. I want the search text value to match the array key, name.
No matter what I type in the text field, it displays "no match found!" and I can never display the names. It seems players[x].name.indexOf() is not recognized. How can I display names?
Here is Fiddle
var players = [
{ "id" : "23012",
"name" : "Scott",
"first" : "Stve",
"last" : "Scott" },
{ "id" : "22904",
"name" : "Phillips, A",
"first" : "Adam",
"last" : "Phillips"},
{ "id" : "45783",
"name" : "Phillips, T",
"first" : "Tom",
"last" : "Phillips" },
{ "id" : "54762",
"name" : "Scobery",
"first" : "Don",
"last" : "Scobery" },
{ "id" : "78903",
"name" : "Phillip",
"first" : "Roger",
"last" : "Phillip"}
]
$("#searchField").on("keyup", function() {
$(".append").empty();
if($("#searchField").val() != ""){
for(var x = 0; x < players.length; x++){
if(players[x].name.indexOf(($("#searchField").val()).toLowerCase()) == 0){
$(".append").append(players[x].name+"<br>");
} else {
$(".append").html("no match found!");
}
}
}
});
Update Fiddle
You are overriding all search results at first negative search.
Because you append append results, at first not found you kill all the appended children with .html() instruction.
It was just that mistake.
I'm not sure about your toLowerCase use, but this is another story.
var players = [{
"id": "23012",
"name": "Scott",
"first": "Stve",
"last": "Scott"
}, {
"id": "22904",
"name": "Phillips, A",
"first": "Adam",
"last": "Phillips"
}, {
"id": "45783",
"name": "Phillips, T",
"first": "Tom",
"last": "Phillips"
}, {
"id": "54762",
"name": "Scobery",
"first": "Don",
"last": "Scobery"
}, {
"id": "78903",
"name": "Phillip",
"first": "Roger",
"last": "Phillip"
}]
$("#searchField").on("keyup", function () {
var found = false;
$(".append").empty();
if ($("#searchField").val() != "") {
for (var x = 0; x < players.length; x++) {
if (players[x].name.indexOf($("#searchField").val()) >= 0) {
found = true;
$(".append").append(players[x].name + "<br>");
}
}
if (!found) {
$(".append").html("no match found");
}
}
}); // searchField on
To have the search completely case insensitive:
if (players[x].name.toLowerCase().indexOf($("#searchField").val().toLowerCase()) == 0)
Spam lowercase around. ( to the object and to the input )
I have an array of objects, like this:
var companies = [
{ "name" : "Company 1",
"logo" : "/logo.gif" },
{ "name" : "Company 2",
"logo" : "/logo2.gif" },
{ "name" : "Company 3",
"logo" : "/logo3.gif" } ];
I want to filter this array to get only values which have a name which exists in another array:
var myCompanies = [ "Company 1", "Company 3" ];
In this example, the data to be returned would be:
var companies = [
{ "name" : "Company 1",
"logo" : "/logo.gif" },
{ "name" : "Company 3",
"logo" : "/logo3.gif" } ];
What's the best way to do this?
You can use $.grep() to get a new, filtered array, like this
var result = $.grep(companies, function(e) {
return $.inArray(e.name, myCompanies) != -1;
});
You can test it here. Note that this performs much better than a $.each() loop, you can test it here: http://jsperf.com/each-vs-grep
By loop only..
var newArray = [];
$.each(companies, function(){
if($.inArray(this.name, myCompanies) !== -1) newArray.push(this);
});
jQuery utilies are used here: jQuery.each() and jQuery.inArray()
This should to the job:
companies = $.map(companies,function(element){
return ($.inArray(element.name,myCompanies)>-1?element:null)
}