splice array base on property value - javascript

$scope.myJson = [{
"id": "1",
"name": "banana",
"price": 12,
"qty": 3,
}, {
"id": "2",
"name": "watermelon",
"price": 12.9,
"qty": 4,
}];
for(i = 0; i < $scope.myJson.length; i++) {
if($scope.myJson[i]._id == '2'){
//what to do here?
//then save back to localstorage
}
}
I'm using localstorage so I have to find array and splice it. I don't know how to proceed.

Splice is the worst option in terms of performance.
Yet in your case you would need to do:
$scope.myJson.splice(i,1);
See performance comparison here: https://jsperf.com/splice-vs-filter
I would at least do a filter:
$scope.myJson = $scope.myJson.filter(function(obj) {
return (obj.id !== '2');
}) ;

Just iterate through the array, search for the desired property value and splice the array.
function spliced(array, value) {
var arr = array.slice(0);
array.forEach(function (obj) {
if (obj.hasOwnProperty('id')) {
if (obj['id'] == value ) {
arr.splice(arr.indexOf(obj),1);
}
}
});
return arr;
}
console.log( spliced(arr, 1) )

Related

Javascript Push to Array if Condition is Met

I have the following Foods Object:
var Foods = {
"Fruits": [{
"id": "1",
"Name": "Granny Smith",
"Category": "1"
}, {
"id": "2",
"Name": "Raspberries",
"Category": "1"
}
],
"Potatoes": [{
"id": "3",
"Name": "Maris Piper",
"Category": "2"
}, {
"id": "4",
"Name": "Charlotte",
"Category": "2"
}]
}
What I would like to do is only push the produce that matches an id passed by a link.
Get Foods
This is what I have tried so far:
function getCat (id){
result = [];
for(let item in Foods) {
if(Foods[item].id == id) {
data[item].foreach(v=>result.push("<div class='box'><h2>" +
data[key].Name + "<br></div>"));
}
}
}
display();
function display() {
alert(result);
}
So if a user hits the link (which has an id of 2), the result array should contain "Charlotte" and "Maris Piper" but I am just drawing a blank.
Any help appreciated.
Cheers
Youre quite close, however theres a slight problem:
for(let item in Foods) {
console.log(Foods[item]);
/*
[{
"id": "1",
"Name": "Granny Smith",
"Category": "1"
}, {
"id": "2",
"Name": "Raspberries",
"Category": "1"
}
]
*/
So youre iterating over the categories, which are arrays.
Foods[item].id
is undefined as its an array and not a product. So we need to iterate the array to, e.g.
var result=[];
Object.values(Foods).forEach(function(category){
category.forEach(function(product){
if(product.id===id){
result.push(product);
}
});
});
Run
But if youre doing this quite often, it might be easier to create one product array once:
var products = Object.values(Foods).reduce((arr,cat)=>arr.concat(cat),[]);
So you can simply filter this whenever someone clicks a button:
var result = products.filter(product=>product.id === id);
Run
You're somewhat on the right track, but what's data? Why are you not doing anything with result? And you should be looking at the Category property rather than ID.
This'll work:
function getCat(id) {
let result = [];
for (let item in Foods) {
if (Foods.hasOwnProperty(item)) {
Foods[item].forEach((food) => {
if (food.Category == id) {
result.push(food);
}
});
}
}
console.log(result);
}
First of all result array should be at global scope so that you can access it in another function, And in object you are having categories then each category has some data in array so after iterating over object, you need to iterate the items from array as well to get the value. Check the below code.
var result = [];
function getCat(id){
for(let item in Foods) {
var foodItem = Foods[item];
for(let i=0; i<foodItem.length; i++){
if(foodItem[i].id == id) {
result.push("<div class='box'><h2>" + foodItem[i].Name + "<br></div>"));
}
}
}
}
function display() {
alert(result);
}
display();
Iterator is wrong. You should do it like this:
function getCat(id){
result = [];
for(let item in Foods) {
Foods[item].forEach(function(each){
if(each.id == id) { // you cmpare to the wrong target
// do something
}
});
}
}

change the value of object using loop [duplicate]

This question already has answers here:
JavaScript Object Mirroring/One-way Property Syncing
(2 answers)
Closed 7 years ago.
I have an object as,
var obj = [
{
"name": "a",
"value": "1"
},
{
"name": "b",
"value": "2"
},
{
"name": "c",
"value": "3"
}
]
I have a large object with more than 50 values.
how can I change the value key using its name
and what is the best looping technique for this.
I tried for loop for this like,
for(i = 0; i < obj.length; i++) {
if(obj[i].name == "b") {
// some other functionality
obj[i].value = "some_value";
}
}
But, it takes long time and sometimes for loop goes for next turn before if condition is executed.
Please explain how to solve it or is there any other looping technique
you can use forEach , but as far your hitting the performance its not best ,
you can use map but native for loop is fastest compared to map too
https://jsperf.com/native-map-versus-array-looping
Map , which runs on the each item of the array and return the new array
obj.map(function(item){
if(item.name === "b"){
item.value = "some_value"
}
return item;
})
You can try this :
$(document).ready(function(){
var obj = [
{
"name": "a",
"value": "1"
},
{
"name": "b",
"value": "2"
},
{
"name": "c",
"value": "3"
}
]
for(i = 0; i < obj.length; i++) {
(function(i){
if(obj[i].name === "b") {
console.log(obj[i].name);
// some other functionality
obj[i].value = "some_value";
}
})(i);
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I think what you had was quite ok. As one of the comments stated, there was a mistake in the IF-statement which prevented it from being triggered.
I am not sure theres a faster way to proces the JSON object than the way you did. Here's a JSFiddle with some small changes.
function ReplaceValue(name, val) {
for (i = 0; i < obj.length; i++) {
if (obj[i].name == name) {
// some other functionality
obj[i].value = val;
break;
}
}
alert(JSON.stringify(obj, null, 2));
}
Map is your friend!
var obj = [
{ "name": "a", "value": "1" },
{ "name": "b", "value": "2" },
{ "name": "c", "value": "3" }
];
var newObj = obj.map((elm) => {
if(elm.name === "b") elm.value = "some value";
return elm;
});
Is this something like what you were looking for?
In lodash you can do something like this:
`
var obj = [
{
"name": "a",
"value": "1"
},
{
"name": "b",
"value": "2"
},
{
"name": "c",
"value": "3"
}
];
_.transform(arr, function(r, n){
if(n.name == 'b'){
r.push({name: n.name, value: 'some value'})}
else{
r.push(n)
}
})
`

Removing Duplicate object from array in jquery code not working

This is my array in jquery , which contains duplicate objects/elements :
[{
"name": "hello",
"label": "world"
}, {
"name": "abc",
"label": "xyz"
}, {
"name": "hello",
"label": "world"
}]
I am using the following piece of code to remove duplicate elements but it not working the duplicate elements are not removed.
var result = [];
$.each(subservices, function (i, e) {
if ($.inArray(e, result) == -1)
result.push(e);
});
alert(JSON.stringify(result));
Function $.inArray works fine for simple types (e.g. number or string), but for complex types it does not produce the correct result, because it tries to match by reference. Instead of using inArray in your loop you can search the array using function grep:
var subservices = [{
"name": "hello",
"label": "world"
}, {
"name": "abc",
"label": "xyz"
}, {
"name": "hello",
"label": "world"
}
];
var result = [];
$.each(subservices, function (i, e) {
var matchingItems = $.grep(result, function (item) {
return item.name === e.name && item.label === e.label;
});
if (matchingItems.length === 0){
result.push(e);
}
});
//displays result [{"name":"hello","label":"world"},{"name":"abc","label":"xyz"}]
alert(JSON.stringify(result));
Here is a working jsFiddle
You need to filter array by unique name/value. Here is some pure JS solution:
var data = [{
"name": "hello",
"label": "world"
}, {
"name": "abc",
"label": "xyz"
}, {
"name": "hello",
"label": "world"
}];
var result = data.filter(function(el, i, x) {
return x.some(function(obj, j) {
return obj.name === el.name && (x = j);
}) && i == x;
});
alert(JSON.stringify(result, null, 4));
This is because these two objects are distinct, even though all the attributes inside are the same. You can see this from:
console.log(result[0] === result[2]);
which results in false.
Instead, you need to iterate through your array based on a unique identifier, such as name & label as such:
for(var i = 0, i < results.length; i++) {
if (result[i].name === ... && result[i].label === ...) {
index = i;
break;
}
}
to check if your item is unique.

programmatically add object properties of arrays

[
{
"uId": "2",
"tabId": 1,
"tabName": "Main",
"points": "10"
},
{
"uId": "3",
"tabId": 2,
"tabName": "Photography",
"points": "20"
}
]
how can I insert into specified array by inspecting its properties values? says I want to add a assoc object into uId = 3, how can I do that? or it's not possible technically?
This is also possible using array.map (Added to the ECMA-262 standard in the 5th edition):
array.map(function(i){
if(i.uId == 3) i['newprop'] = 'newValue';
});
Example Here.
Update: It could be an array
if(i.uId == 3) i['newprop'] = ['newvalue1', 'newvalue2'];
Example2 Here.
They look like JSON data , so json_decode() to an array , search for the UId value and then add the corresponding assoc value and after the end finally wrap them up using json_encode()
foreach($array as $k=>&$arr)
{
if($arr->{'uId'}==2)
{
$arr->{'somecol'}="Hey";
}
}
echo json_encode($array,JSON_PRETTY_PRINT);
OUTPUT :
[
{
"uId": "2",
"tabId": 1,
"tabName": "Main",
"points": "10",
"somecol": "Hey"
},
{
"uId": "3",
"tabId": 2,
"tabName": "Photography",
"points": "20"
}
]
var array = [
{
"uId": "2",
"tabId": 1,
"tabName": "Main",
"points": "10"
},
{
"uId": "3",
"tabId": 2,
"tabName": "Photography",
"points": "20"
}
];
for ( var i = 0; i < array.length; i++ ) {
if ( array[i].uId == 3) {
array[i].someProp = "Hello";
break; // remove this line for multiple updates
}
}
Or you can make a function like this:
function getMatch(data, uid) {
for ( var i = 0; i < data.length; i++ ) {
if ( data[i].uId == 3) {
return data[i];
}
}
}
and use it like this:
getMatch(array, 3).someproperty = 4;
You can use the map function, which executes a function on each element of an array
a.map(function(el) {
if (el.uId == 3) {
el.prop = "value";
}
});
Or you can use the filter function.
// Get the array of object which match the condition
var matches = a.filter(function(x) { return x.uId == 3 });
if (matches.length > 0) {
matches[0].prop = "value";
}

How apply ko.utils.arrayGetDistinctValues on two dimensional arrays

I have an ko.observableArray with two dimensions, i.e. "id" and "name".
Id will always be distinct, but name can hold the same value.
self.myArray = ko.observableArray( [
{ "id": "1", "name": "Barbara" }, 
{ "id": "2", "name": "Edwin" }, 
{ "id": "3", "name": "Barbara" } 
] );
However I want to filter the array so that my result holds only the first occurrence of "name".
The result I want is:
self. myFilteredArray = [
{ "id": "1", "name": "Barbara" }, 
{ "id": "2", "name": "Edwin" } 
];
I have been trying to figure this out using ko.utils.arrayGetDistinctValues(), but how can I utilize it on solely one chosen dimension?
You could use a computed for this:
viewModel.myFilteredArray = ko.computed(function() {
var rv = [], names = [];
for(var i=0; i<this.myArray().length; i++) {
if(names.indexOf(this.myArray()[i].name) === -1) {
rv.push(this.myArray()[i]);
names.push(this.myArray()[i].name);
}
}
return rv;
}, viewModel);
I can suggest a function, that loops through the array, builds map of property values for each item and checks, whether the current value was already added. Something like this:
function filterByFirstOccurance(arr, prop) {
var propValuesHash = {},
result = [];
for (var i = 0, l = arr.length; i < l; i++) {
var item = arr[i],
propValue = item[prop];
if (item.hasOwnProperty(prop) && !propValuesHash[propValue]) {
propValuesHash[propValue] = true;
result.push(item);
}
}
return result;
};
Fiddle

Categories

Resources