Remove an object from array - javascript

am trying to remove an object from an Array list within a JavaScript object.
The Structure if the Object:
{
"temp": {
"name": "",
"css": {
"bg_color_main": "#xxxxx",
"part_bg_color": "xxxxx",
"txt_font_family": "xxxxxxxx",
"txt_font_color_main": "#xxxxx",
"headline_font_family": "xxxxx",
},
"part": [
{
"name": "xxxxxx",
"style": {}
},
{
"name": "yyyyyy",
"style": {}
},
{
"name": "zzzzzz",
"style": {}
}
]
}
}
The Code:
$.each(jsonData.temp.part, function(k, v) {
var tt = this; //var tt = $(this)
if( v.name === partName ){
delete tt[k];
}
});
Nothing happens.. no error, no warning!

There are two problems in your code. First, delete does not remove elements. It only sets them to undefined. Use splice instead.
Second, it never gets to do that, because tt (or this) is the object inside the array that you are currently working on, not the array you are iterating. You need to access the array explicitly with its full name.
$.each(jsonData.temp.part, function(k, v) {
var tt = this; //var tt = $(this)
if( v.name === partName ){
jsonData.temp.part.splice(k,1);
}
});

Alternatively you could simply use a filter.
var o = {
"temp": {
"name": "",
"css": {
"bg_color_main": "#xxxxx",
"part_bg_color": "xxxxx",
"txt_font_family": "xxxxxxxx",
"txt_font_color_main": "#xxxxx",
"headline_font_family": "xxxxx",
},
"part": [
{
"name": "xxxxxx",
"style": {}
},
{
"name": "yyyyyy",
"style": {}
},
{
"name": "zzzzzz",
"style": {}
}
]
}
}
o.temp.part = o.temp.part.filter(function (element) {return element.name !== "zzzzzz"});

You could use different approach, for example:
If the reference of the array is not needed, you can use reduce to create a new array:
jsonData.temp.part = jsonData.temp.part.reduce(function(acc, value) {
if( value.name !== partName ){
acc.push(value);
}
return acc;
}, []);
Also you can find the index of the element, and use splice to mantain the reference:
var indexElement = jsonData.temp.part.reduce(function(acc, value, index) {
if( value.name !== partName ){
return index;
}
return acc;
}, -1);
jsonData.temp.part.splice(indexElement, 1)
Both ways work.

Here is a possible solution:
The simplest way is to use delete.
var jsonData = {
"temp": {
"name": "",
"css": {
"bg_color_main": "#xxxxx",
"part_bg_color": "xxxxx",
"txt_font_family": "xxxxxxxx",
"txt_font_color_main": "#xxxxx",
"headline_font_family": "xxxxx",
},
"part": [
{
"name": "xxxxxx",
"style": {}
},
{
"name": "yyyyyy",
"style": {}
},
{
"name": "zzzzzz",
"style": {}
}
]
}
}
var nameToRemove = 'xxxxxx';
var parts = jsonData.temp.part;
$.each(parts, function(k, v) {
if (v.name === nameToRemove)
{
delete parts[k];
}
});
//this code is added to just show the result
$.each(parts, function(i, r){
if (r != undefined)
{
$('#result').append(r.name + ',')
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label id="result"></label>

You created a copy and delete item from the copy.
$.each(jsonData.temp.part, function(k, v) {
var tt = this; // now you created a new array!!!
if( v.name === partName ){
delete tt[k]; // here you delete the item from the copy array
delete this[k]; // you remove item from the original array
}
});

Related

Grab Keys from JSON Array Without Repeating

Consider the following JSON array returned from a request sent to an Elasticsearch cluster:
[
{
"_type": "Event example",
"_source": {
"democarrier_s": "vodafone UK",
"m-Ecosystem_s": "iOS",
"demo-application": "demo",
"demo-country-code": "GB"
}
},
{
"_type": "Event example",
"_source": {
"democarrier_s": "Verizon",
"m-Ecosystem_s": "iOS",
"demo-application": "demo1",
"demo-country-code": "US"
}
}
]
I am trying to figure out how to grab all of the unique keys from this document without repeating and without hard-coding any of the values and store them into an object of the following form:
columns = ['_type', '_source.democarrier_s', '_source.m-Ecosystem_s', '_source.demo-application', '_source.demo-country-code'];
Could someone help me figure out how to achieve this? I've been trying to loop through the document and store the keys but I can't quite figure it out. '_type' can be hard coded into the columns object because it will always exist.
Thank you in advance for your help and time.
If it's just 2 levels you could do this:
var data = [
{
"_type": "Event example",
"_source": {
"democarrier_s": "vodafone UK",
"m-Ecosystem_s": "iOS",
"demo-application": "demo",
"demo-country-code": "GB"
}
},
{
"_type": "Event example",
"_source": {
"democarrier_s": "Verizon",
"m-Ecosystem_s": "iOS",
"demo-application": "demo1",
"demo-country-code": "US"
}
}
]
var keys = [];
data.forEach(function(item) {
for (var key in item) {
var hasProperties = false;
if (typeof item[key] !== 'string') {
for (var key2 in item[key]) {
hasProperties = true;
var keyName = key + "." + key2;
if (keys.indexOf(keyName) < 0)
keys.push(keyName);
}
}
if (!hasProperties && keys.indexOf(key) < 0) {
keys.push(key);
}
}
});
keys.forEach(function (k) { console.log(k) });

Loop through object and replace values

I have an object which at some points is four levels deep, however I want a function that will cope should more levels be introduced. I'm trying to write a function that will replaced elements such that <span class="ajax-parent1-parent2-parent3-value"></span> will be replaced with parent1.parent2.parent3.value.
The issue is that the depth is variable, so I could have something like <span class="ajax-parent1-value"></span> to be replaced with parent1.value.
Finally, it's not always the text to be replaced. Optionally, data-attr can specify an attribute to be used instead (through element.attr(<data-attr>, <value>)).
Currently, I'm iterating manually, however it isn't very clean so I was wondering if there is a better way to do it. This also doesn't work for greater than two levels deep.
function render(data) {
$.each(data, function(parent, value) {
$.each(value, function(element, value) {
$el = $('.ajax-' + parent + '-' + element);
$.each($el, function(key, el) {
if ($(el).data('attr')) {
$(el).attr($(el).data('attr'), value);
} else {
$(el).text(value);
}
}
});
});
}
Example object:
{
"profile": {
"username": "johnd",
"bio": "Some example data about John",
"website": "http://john.com",
"profile_picture": "http://john.com/me.jpg",
"full_name": "John Doe",
"counts": {
"media": 13,
"followed_by": 26,
"follows": 49
},
"id": "16"
},
"dashboard": {
"script": {
"tags": ["media"],
"stats": {
"liked": 0,
"lastrun": "never",
"duration": 0
},
"status": {
"code": 0,
"slug": "disabled",
"human": "Disabled",
"message": "Not running."
}
},
"account": {
"plan": "free",
"created": 1419261005373,
"updated": 1419261005373
}
},
"serverInformation": {
"serverName": "Johns API",
"apiVersion": "0.0.1",
"requestDuration": 22,
"currentTime": 1419262805646
},
"requesterInformation": {
"id": "redacted",
"fingerprint": "redacted",
"remoteIP": "redacted",
"receivedParams": {
"action": "getDashboard",
"apiVersion": 1
}
}
}
Here is the solution I wrote:
function iterate(obj, stack) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property], stack + '-' + property);
} else {
$group = $('.ajax' + stack + '-' + property);
$.each($group, function(key, element) {
if ($(element).data('attr')) {
$(element).attr($(element).data('attr'), obj[property]);
} else {
$(element).text(obj[property]);
}
});
}
}
}
}
Why don't you start from the HTML, so you only access the properties you actually want to render?
That way you can keep it quite simple (also note that this removes the need to nest HTML spans in the same order/depth as the data object, you can just place any HTML node anywhere. Just make sure you don't use class/node names more then once.
function parseData(data) {
var $container = $('.ajax');
$container.find("[class^='ajax-']").each(function(i, el) {
var $el = $(el);
if ($el.children().length === 0)
{
var nodes = $el.attr('class').split('-');
nodes.shift();
var node = data;
for (var i = 0; i < nodes.length; i++) {
node = node[nodes[i]];
if (typeof(node) == "undefined") {
break;
}
}
if ($el.data('attr'))
{
$el.attr($el.data('attr'), node);
}
else
{
$el.text(node);
}
}
});
}
Fiddle here:
http://jsfiddle.net/ckcduLhn/5/

Remove objects/fields which contains a specific word

I have a JSON file; I want to remove all of the fields or objects, whose names are a specific word (lets say "test") and then return the stripped JSON file back; how can I do it in Node.JS?
Here is an example of my JSON file:
{
"name": "name1",
"version": "0.0.1",
"storage": {
"db": {
"test": "STRING",
"tets2": "STRING",
},
"test": {
"test11": "STRING",
"test2": {
"test3": "0",
"test4": "0"
},
"test5": {
"test6": "0",
"test7": "0"
}
},
"test8": {
"test9": "STRING",
"test10": "STRING"
}
}
}
The desired output:
{
"name": "name1",
"version": "0.0.1",
"storage": {
"db": {
"tets2": "STRING",
},
"test8": {
"test9": "STRING",
"test10": "STRING"
}
}
}
I tried the folloiwng, but I dont know how to use typeof() and check if it is an objectgo deeper in the tree! could you please help me in this regard
var new_json = config;
async.each(Object.keys(config), function(key) {
if (key == "test") {
delete new_json[key];
}
while (typeof (new_json[key]) == "object") {
// How can I handle it here
}
});
console.log("done!");
This function should do it:
function clean(obj,target) {
var tmpobj = obj;
for (var key in tmpobj) {
if (key === target) {
delete obj[key];
}
else if (typeof obj[key] === "object") {
obj[key] = clean(obj[key],target);
}
}
return obj;
}
called this way:
json_struct = clean(json_struct,"test")
Below Recursion code will work. But you need to list of acceptable fields or not acceptable fields and based on that you need to change the below condition IF you know not acceptable fields then use below conditions.
unAcceptableFields.indexOf(key) > 0
var acceptableFields = ["name","version","storage","db", "test9", "test10","tets2", "test8", "test9", "test10" ];
console.log(removeUnwantedFields(testObject, acceptableFields));
function removeUnwantedFields(jsData,acceptableFields) {
var key;
if (jsData) {
for (key in jsData) {
if (acceptableFields.indexOf(key) == -1) {
delete jsData[key];
}
else if(typeof jsData[key] === "object"){
jsData[key] = removeUnwantedFields(jsData[key],acceptableFields);
}
}
}
return jsData;
}
Refer this URL http://jsfiddle.net/55x2V/

Change key name in nested JSON structure

I have a JSON data structure as shown below:
{
"name": "World",
"children": [
{ "name": "US",
"children": [
{ "name": "CA" },
{ "name": "NJ" }
]
},
{ "name": "INDIA",
"children": [
{ "name": "OR" },
{ "name": "TN" },
{ "name": "AP" }
]
}
]
};
I need to change the key names from "name" & "children" to say "key" & "value". Any suggestion on how to do that for each key name in this nested structure?
I don't know why you have a semicolon at the end of your JSON markup (assuming that's what you've represented in the question), but if that's removed, then you can use a reviver function to make modifications while parsing the data.
var parsed = JSON.parse(myJSONData, function(k, v) {
if (k === "name")
this.key = v;
else if (k === "children")
this.value = v;
else
return v;
});
DEMO: http://jsfiddle.net/BeSad/
Try this:
function convert(data){
return {
key: data.name,
value: data.children.map(convert);
};
}
Or if you need to support older browsers without map:
function convert(data){
var children = [];
for (var i = 0, len = data.children.length; i < len; i++){
children.push(convert(data.children[i]));
}
return {
key: data.name,
value: children
};
}
You could use a function like this :
function clonerename(source) {
if (Object.prototype.toString.call(source) === '[object Array]') {
var clone = [];
for (var i=0; i<source.length; i++) {
clone[i] = goclone(source[i]);
}
return clone;
} else if (typeof(source)=="object") {
var clone = {};
for (var prop in source) {
if (source.hasOwnProperty(prop)) {
var newPropName = prop;
if (prop=='name') newPropName='key';
else if (prop=='children') newPropName='value';
clone[newPropName] = clonerename(source[prop]);
}
}
return clone;
} else {
return source;
}
}
var B = clonerename(A);
Note that what you have isn't a JSON data structure (this doesn't exist as JSON is a data-exchange format) but probably an object you got from a JSON string.

searching a nested javascript object, getting an array of ancestors

I have a nested array like this:
array = [
{
"id": "67",
"sub": [
{
"id": "663",
},
{
"id": "435",
}
]
},
{
"id": "546",
"sub": [
{
"id": "23",
"sub": [
{
"id": "4",
}
]
},
{
"id": "71"
}
]
}
]
I need to find 1 nested object by its id and get all its parents, producing an array of ids.
find.array("71")
=> ["546", "71"]
find.array("4")
=> ["546", "23", "4"]
What's the cleanest way to do this? Thanks.
Recursively:
function find(array, id) {
if (typeof array != 'undefined') {
for (var i = 0; i < array.length; i++) {
if (array[i].id == id) return [id];
var a = find(array[i].sub, id);
if (a != null) {
a.unshift(array[i].id);
return a;
}
}
}
return null;
}
Usage:
var result = find(array, 4);
Demo: http://jsfiddle.net/Guffa/VBJqf/
Perhaps this - jsonselect.org.
EDIT: I've just had a play with JSONSelect and I don't think it's appropriate for your needs, as JSON does not have an intrinsic 'parent' property like xml.
It can find the object with the matching id, but you can't navigate upwards from that. E.g.
JSONSelect.match(':has(:root > .id:val("4"))', array)
returns me:
[Object { id="4"}]
which is good, it's just that I can't go anywhere from there!

Categories