Delete an element inside a JSON array by value with jQuery - javascript

Part of my json Array
var videos = $j.parseJSON('
[
{ "privacy":"public",
"id":"1169341693" },
{ "privacy":"private",
"id":"803641223" },
{ "privacy":"public",
"id":"1300612600" }, ......
When I console.log the element I'm getting
[Object, Object, Object, …]
0: Object
privacy: "public"
id: "1169341693"
1: Object
privacy: "private"
id: "803641223"
2: Object
privacy: "public"
id: "1300612600"
I also have a unique id I want to search for
var uniqueId = 803641223;
I want to find, in my videos array, the right id, and delete that whole array element. So In that case, I want my final videos array to contain only 2 object, instead of 3 :
var videos = $j.parseJSON('
[
{ "privacy":"public",
"id":"1169341693" },
{ "privacy":"public",
"id":"1300612600" }, ......
My problem is how to get in the array to do my splice. I prefer to do it with jQuery
Any help please?

You can use grep :
videos = $.grep(videos, function(e) { return e.id!='803641223' });
In vanilla JavaScript you could have used the similar filter function but it's not supported by IE8.
Please note that videos is a JavaScript array, it's not a JSON array, even if it was made by parsing a JSON string.

A non-jQuery solution that modifies the array in place:
var uniqueId = 803641223;
var videos = [
{ "privacy":"public",
"id":"1169341693" },
{ "privacy":"private",
"id":"803641223" },
{ "privacy":"public",
"id":"1300612600" }
];
function cleaner(arr, id) {
for (var i = 0; i < videos.length; i++) {
var cur = videos[i];
if (cur.id == uniqueId) {
arr.splice(i, 1);
break;
}
}
}
cleaner(videos, uniqueId);
http://jsfiddle.net/4JAww/1/
Note that this modifies the original array in place, such that the original videos array will have the items you want, and the one that matched the uniqueId will be gone (forever). So it depends on whether you want to be able to access the original array ever again, or are okay with modifying it.
It just loops through the elements of the array, compares the item's id property to the uniqueId value, and splices if they match. I use break; immediately after the splice because you seem to imply that the uniqueId can/should only appear once in the array since it's...unique.

Hello you can remove element with javascript splice function...
videos.items.splice(1, 3); // Removes three items starting with the 2nd,

It worker for me.
arrList = $.grep(arrList, function (e) {
if(e.add_task == addTask && e.worker_id == worker_id) {
return false;
} else {
return true;
}
});
It returns an array without that object.
Hope it helps.

Related

How to assign specific objects of an array into another array of objects?

I have array of objects named tickets and I want to pick some specific objects from tickets like number,desc and state and assign them to new array of objects say myarr. I'm writing the below code but it says number is undefined. What am I doing wrong ?
$scope.myarr=[{
number:"",
desc:"",
state:""
}
];
for(var i=0;i<$scope.tickets.length;i++){
$scope.myarr[i].number=$scope.tickets[i].number;
$scope.myarr[i].desc=$scope.tickets[i].short_description;
$scope.myarr[i].state=$scope.tickets[i].state;
}
You need do something like this.
$scope.myarr=[];
for(var i=0;i<$scope.tickets.length;i++){
//Your Conditions
var object={
"number":$scope.tickets[i].number,
"desc" :$scope.tickets[i].short_description,
"state":$scope.tickets[i].state
}
$scope.myarr.push(object);
}
$scope.myarr = [];
angular.forEach($scope.tickets, function(ticket) {
this.push({number:ticket.number, state: ticket.state});
}, $scope.myarr);
If you don't need to support IE < 9, there is a handy function called map which is useful in this case
$scope.myarr = $scope.tickets.map(function(ticket) {
// return the element to be inserted in the new array
return {
number: ticket.number,
desc: ticket.short_description,
state: ticket.state
};
});

Null Values in array of objects

I am creating objects when textbox having some values (using ng-blur and textbox.value!==undefined) and then putting these objects in an array (all working fine here).
When I click on checkbox (checkbox model bind with textbox ng-required) I need to delete that particular object having that textbox value.
I am using:
arr.splice(index,1);
to remove that particular object from array (by matching it's name like "monthly" or "quarterly" etc.), but it is creating null at that particular position.
for e.g. [object,object,object]
[
{name:"monthly",
amount:1000 },
{name:"quarterly",
amount:1200 },
{name:"yearly",
amount:1300 }
]
after removing all element it shows [] and when I add another new object it displays [3:object] and it's content as [null,null,null,object];
or
if I remove middle object say name:"quarterly", it shows [object,object] but after adding a new object it display array as [object,object,null,object] with length of array as 4.
Why is there null and how can I remove that from array. (don't want to iterate again to check null).
It is difficult to say why your code creates the null values without have a look to it.
But I can say you that it is not the expected behaviour.
You can see this example to get some inspiration:
var data = [
{name:"monthly",
amount:1000 },
{name:"quarterly",
amount:1200 },
{name:"yearly",
amount:1300 }
];
var newObjectToBeAdded = { name: "daily", amount:"100" }
function showObjects()
{
document.body.innerHTML += data + '<hr>';
}
function deleteObjectByName( objectName )
{
for( var i = 0; i < data.length; i++ )
{
if( data[ i ].name == objectName )
{
data.splice(i, 1);
}
}
}
function addObjectToData( newObject )
{
data.push( newObject );
}
showObjects();
deleteObjectByName( "quarterly" );
showObjects();
addObjectToData( newObjectToBeAdded );
showObjects();
Just to throw a guess out, maybe you are accidentally duplicating the array. Maybe in some point of your code you are doing something like this:
var new_array = original_array.splice( index );
Or creating the new array in the loop you use to find the target object, or using some kind of intermediate array, etc.
Hope it helps!
var arrayWithoutNulls = myArray.filter(function(val) {
if (val) {
return val;
}
});

How to use javascript to loop through key , values and add up one key's value when the other's match

I have a dataset of records that look like this :
[{
"d1d":"2015-05-28T00:00:00.000Z",
"d1h":0,
"d15m":0,
"ct":3
},
{
"d1d":"2015-05-28T00:00:00.000Z",
"d1h":0,
"d15m":0,
"ct":1
}
]
The ct value changes in every record. If d1d, d1h, and d15m are the same in one or more records, I need to combine those records into one with the sum of all the ct values.
I do have jquery, can I use grep for this?
I realize the server side could do a better job of getting me this data , but I have zero control over that.
You don't have to use jQuery for this, vanilla JavaScript will do.
I'll show you two solutions to your problem;
Example 1: Abusing Array#reduce as an iterator
var intermediaryArray = [];
dataset.reduce(function(prev, curr) {
if(prev.d1d === curr.d1d && prev.d1h === curr.d1h && prev.d15m === curr.d15m) {
intermediaryArray.push({
d1d: prev.d1d,
d1h: prev.d1h,
d15m: prev.d15m,
ct: prev.ct + curr.ct
});
} else {
// push the one that wasn't the same
intermediaryArray.push(curr);
}
// return current element so reduce has something to work on
// for the next iteration.
return curr;
});
Example 2: Using Array#Map and Array#Reduce in conjunction
This example utilises underscore.js to demonstrate the logic behind what you want to do.
.map() produces the new array of grouped objects.
.groupBy() produces an array of subarrays containing the objects that pass the predicate that all objects must share the same d1d or grouping function.
.reduce() boils all subarrays down to one value, your object with both cts added to each other.
var merged = _.map(_.groupBy(a, 'd1d'), function(subGroup) {
return subGroup.reduce(function(prev, curr) {
return {
d1d: prev.d1d,
d1h: prev.d1h,
d15m: prev.d15m,
ct: prev.ct + curr.ct
};
});
});
Here's one possible solution:
var dataset = [{
"d1d":"2015-05-28T00:00:00.000Z",
"d1h":0,
"d15m":0,
"ct":3
},
{
"d1d":"2015-05-28T00:00:00.000Z",
"d1h":0,
"d15m":0,
"ct":1
}
]
function addCt(dataset) {
var ctMap = {}
var d1d, d1h, d15m, ct, key, value
for (var ii=0, record; record=dataset[ii]; ii++) {
key = record.d1d+"|"+record.d1h+"|"+record.d15m
value = ctMap[key]
if (!value) {
value = 0
}
value += record.ct
ctMap[key] = value
}
return ctMap
}
ctMap = addCt(dataset)
console.log(ctMap)
// { "2015-05-28T00:00:00.000Z|0|0": 4 }
You may want to construct the key in a different way. You may want set the value to an object containing the d1d, d1h, d15m and cumulated ct values, with a single object for all matching d1d, d1h and d15m values.

Get all string values from a nested object

I have an object, with nested objects. How do I target a specific index of the object and loop through all the nested values of image. As you will note the length of the nested objects vary.
Target example: productArray[0].image = test1.png, test2.png, test3.png
var products = [
//item1
{
identifier: "item-0",
image: {
"img1": "test1.png",
"img2": "test2.png",
"img3": "test3.png"
}
},
//item2
{
identifier: "item-1",
image: {
"img1": "test1.png",
"img2": "test2.png"
}
},
//item3
{
identifier: "item-2",
image: {
"img1": "test1.png",
"img2": "test2.png",
"img3": "test3.png",
"img4": "test4.png",
"img5": "test5.png",
"img6": "test6.png",
"img7": "test7.png"
}
}
];
We can do this. What you need to do is a simple loop through the object at a specific index, or you can target them all. Note that the image object is not an array, so it will not have an accurate length property.
Target all indexes:
for(var i = 0; i < products.length; i++) {
console.log("Item: " + i);
var images = products[i].image;
for(var a in images)
console.log(images[a]);
}
Target specific:
for(var i in products[0].image)
console.log(products[0].image[i]);
I used a for loop here, but you can use a while loop if you would like.
example
Steps:
You need to iterate over your original array of products. products
Each element (product) will be in format { identifier: "", image : {"img1" : "img2", ..}} products[i]
You get the image property of current product - this is an object. products[i].image
Now you need to iterate over the properties of the image object. products[i].image[j]
Code:
for(var i = 0; i < products.length; i++)
{
for(var j in products[i].image)
{
// Here you have all the images for the current product.
// You can print them, group them or whatever you want to do with them
console.log(products[i].image[j]);
}
}
Also you can change the code (introduce variables) to be more readable.
var strs = (function( obj ) {
var ret = [];
for( im in obj ) {
ret.push( obj[im] );
//You could access each image URL here
//ad strs in the end will have all of them
//comma-separated after this code completes
// im is the key, obj[ im ] the value
}
return ret.join(',');
})( products[0].image );
console.log( strs );
WORKING JS FIDDLE DEMO
Here is another way of doing this, with newer functions in ECMAScript 5
var images = Object.keys(products[2].image).map(function(key){
return products[2].image[key]
})
console.log(images) // Returns: ["test1.png", "test2.png", "test3.png", "test4.png", "test5.png", "test6.png", "test7.png"]
How It Works:
Object#keys returns an array of key names. Array#map creates a new array using the keys from Object#keys. By looking up the key from the object you get the value, which will be the image name.
JS FIDDLE

Get the lower integer id not already used in Javascript

I have a list of JS objects defined by an integer ID.
objects = [{
id: 0,
type: 'null'
}, {
id: 1,
type: 'foo'
}, {
id: 2,
type: 'bar'
}];
I implemented a function to remove an element from my list :
removeObject = function(o){
objects.splice(objects.indexOf(o), 1);
}
My problem is that I need to create a function to add a new item in my list with a id not already used (for example the lower positive integer not present in the list).
I tried to do something like that but it did not work when I remove the object 0 (for example).
addObject = function(type){
objects.push({
id: objects.length,
type: type
});
};
How can I do this ?
EDIT 1
According to your answers, I assume that the best solution in term of performance is to just use a topId which is always incremented when I add a new object in my list.
But that do not answer to my requierement. Actually I think that #X-Pippes response could be good.
Should I do someting like that :
objects = [{
id: 0,
type: 'null'
}, {
id: 1,
type: 'foo'
}, {
id: 2,
type: 'bar'
}];
// Init available ids list with the default value
availableIds = [objects.length];
removeObject = function(o){
// Remove the object from the list
objects.splice(objects.indexOf(o), 1);
// Add its id to the available ids list
availableIds.push(o.id);
}
addObject = function(type){
// Get lower id available
var newId = Math.min.apply(Math,availableIds);
// Push the new object with the id retrieved
objects.push({
id: newId,
type: type
});
// Remove used id from the available ids list
availableIds.splice(availableIds.indexOf(newId), 1);
// Add a default id if available list is empty
if(availableIds.length < 1) availableIds.push(objects.length);
};
if you remove for instance 0 and the next addObject is 0 you have to do something like:
keep a list [initial empty] with every ID removed. When you need to add a new one, pick the shorter, add and delete from list.
Also keep a var with the biggest ID added. If the previous list is empty, add +1 to the var and addObject with that id
Use the correct structures. A JavaScript object will do the job. It guarantees that you only get one item for key, you can look up and remove by key in probably O(1)ish. No point trying to re-implement it in a less efficient manner, which will be O(n) lookup.
var structure = {
objects : {},
topId : 0
}
structure.add = function(item) {
var id = this.topId ++;
structure.objects[id] = item;
}
structure.add("thing")
structure.add("other thing")
structure.add("another thing")
structure.objects
>>> Object {0: "thing", 1: "other thing", 2: "another thing"}
structure.objects[1]
>> "other thing"
Then the normal index operations to get/set/delete.
If you use that function then you have an invariant (guarantee) on your data structure that you won't use the same ID twice.
You need a function to find the first free number:
addObject = function(type){
objects.push({
id: firstOpenIndex(),
type: type
});
};
firstOpenIndex = function() {
for(var idx = 0; true; i++) {
var found = false;
for(var o in objects) {
if (objects[o].id == idx) {
found = true;
break;
}
}
if (!found) return idx;
}
}
In Javascript MaxInt is 9007199254740992. Why not just keep incrementing?
You can and probably should just use an array(s) like:
objects.type=['null','foo','bar'];
to add an object see:
How to append something to an array?
to find a value: var index = objects.type.indexOf('foo');
to find 1st empty field var index = objects.type.indexOf(''); which you can use to find the element for adding (if index is -1 use objects.type.length) if you "delete" an element by setting it to "" or... unless you have specific reason for keeping the "ID" static (in this case the array index), remove the element and only append new ones to the end
to remove an element see:
How do I remove a particular element from an array in JavaScript?
which will allow you to just push/append the next data.
if you need a new object array with empty fields to fill because you get new data to track:
object.newField=new Array(objects.type.length);
If you get to this point where your object contains multiple arrays, you will probably want to create functions for insert/add and delete/remove, so you don't do an operation on 1 and not the other.
Everything is already built in (read likely already pretty fast) and you don't need to reinvent constructors for your really cool object type.

Categories