javascript find object in array by value and append additional value - javascript

I think the title explains it well enough. I've got an array that has two values per object and I need to look up the object by one of those values then assign a third to it.
Here are the guts:
$slides.push({
img: el.attr('href'),
desc: el.attr('title').split('Photo #')[1]
});
Which builds an array as such:
Object
desc: 127
img: img/aaron1.jpg
Object
desc: 128
img: img/aaron2.jpg
I'd like to look up the desc value, then assign a third value of in: yes
$slides.findInArray('desc', '127').addValueToObject('in','yes')

http://jsfiddle.net/S3cpa/
var test = [
{
desc: 127,
img: 'img/aaron1.jpg',
},
{
desc: 128,
img: 'img/aaron2.jpg',
}
];
function getObjWhenPropertyEquals(prop, val)
{
for (var i = 0, l = test.length; i < l; i++) {
// check the obj has the property before comparing it
if (typeof test[i][prop] === 'undefined') continue;
// if the obj property equals our test value, return the obj
if (test[i][prop] === val) return test[i];
}
// didn't find an object with the property
return false;
}
// look up the obj and save it
var obj = getObjWhenPropertyEquals('desc', 127);
// set the new property if obj was found
obj.in = obj && 'yes';

easy way
for (var i = 0; i < $slides.length; i++)
{
if ($slides[i]["desc"] == "TEST_VALUE")
{
$slides[i]['in']='yes';
}
}
Another way
Array.prototype.findInArray =function(propName,value)
{
var res={};
if(propName && value)
{
for (var i=0; i<this.length; i++)
{
if(this[i][propName]==value)
{
res = this[i];
break;
}
}
}
return res;
}
Object.prototype.addValueToObject =function(prop,value)
{
this[prop]=value;
}
---Using It--
$slides.findInArray('desc', '127').addValueToObject('in','yes');
http://jsfiddle.net/s6ThK/

You need to run it through a for loop
// Loop through the array
for (var i = 0 ; i < $slides.length ; i++)
{
// Compare current item to the value you're looking for
if ($slides[i]["desc"] == myValue)
{
//do what you gotta do
$slides[i]["desc"] = newValue;
break;
}
}

With modern JS it can be simply done:
var obj = $slides.find(e => e.desc === '127');
if (obj) {
obj.in = 'yes';
}

Related

Merge Nested arrays in Javascript

I am a javascript beginner. I need to merge two arrays which contains objects which in turn contain arrays.
I have two arrays
arr1[
{
description : "this is a object",
array : [a.x,"b"]
}
]
arr2[
{
array : [a.z,"b","c","d"]
}
]
I have used the following code to perform the merge
function arrayUnique(array) {
var a = array.concat();
for(var i=0; i<a.length; ++i) {
for(var j=i+1; j<a.length; ++j) {
if(a[i] === a[j])
a.splice(j--, 1);
}
}
return a;
}
function combine(obj1,obj2) {
var res = {};
for (var k1 in obj1) {
if (!obj1.hasOwnProperty(k1)) continue;
if (obj2.hasOwnProperty(k1)) { // collision
if (typeof(obj1[k1]) !== typeof(obj2[k1])) throw "type mismatch under key \""+k1+"\".";
if (Array.isArray(obj1[k1])) {
res[k1] = obj1[k1].concat(obj2[k1]);
} else if (typeof(obj1[k1]) === 'string' || obj1[k1] instanceof String) {
res[k1] = arrayUnique(obj1[k1].concat(obj2[k1]));
} else if (typeof(obj1[k1]) === 'object') {
res[k1] = combine(obj1[k1],obj2[k1]);
} else {
throw "unsupported collision type "+typeof(obj1[k1])+" under key \""+k1+"\".";
}
} else {
res[k1] = obj1[k1];
}
}
for (var k2 in obj2) {
if (!obj2.hasOwnProperty(k2)) continue;
if (obj1.hasOwnProperty(k2)) continue; // already handled it above
res[k2] = obj2[k2];
}
return res;
}
var res = combine(arr1,arr2);
This is the result i expect
res = { description : "this is a object", array : [a.x,a.z,"b","c","d"] }
But unfortunately this is the result i get
res = { description : "this is a object", array : [a.x,"b","c","d"]}
a.z is ommited.
When both objects have the same array field you concatenate them (concat append the two arrays one after another), here:
if (Array.isArray(obj1[k1])) {
res[k1] = obj1[k1].concat(obj2[k1]);
If instead of ["a","a","b","b","c","d"] you want to get ["a","b","c","d"] you need to perform the array merge manually.
Check this answer for multiple ways to merge arrays without duplicates.

How do I SET to the Object's properties if I have a path array to the needed property?

var obj = {
people: {
John: {
pets:{
dog:{
name:"Umbrella",
age:12
},
cat:{
name:"Kitty",
age:5
}
}
}
}
};
var path=['people', 'John', 'pets', 'cat', 'name'];
var newName='Train';
How do I SET what the array wants (now it is cat's name) to the object? The array can be changed, so I can not write it by hand. I need a function to do it automatically depending on the array
You can use a recursive function like this one:
var prop = function (obj, chain) {
if (obj && chain.length > 0) {
return prop(obj[chain[0]], chain.slice(1));
}
return obj;
};
prop(obj, path);
Or even an iterative function:
var prop = function (obj, chain) {
var i = 0;
while (obj && i < chain.length) {
obj = obj[chain[i]];
i++;
}
return obj;
};
prop(obj, path);
EDIT: To set a value, you can do something like this:
var set = function (obj, chain, value) {
if (obj === undefined || obj === null) return;
var i = 0;
while (obj[chain[i]] !== undefined && obj[chain[0]] !== null && i < chain.length - 1) {
obj = obj[chain[i]];
i++;
}
obj[chain[i]] = value;
};
set(obj, path, 'Train');
use the below function recursively
foreach(var key in obj)
{
console.log('key'); //gives the key name like - people, John, Pets, dog, cat etc.,
}
Using for loop:
var cursor = obj;
for (var i = 0, len = path.length; i < len; i++) {
cursor = cursor[path[i]];
}

indexOf() when array-elements are objects (javascript)

For instance, a variable named arrayElements of type array contains:
[{id:1, value:5},{id:2, value:6},{id:3, value:7},{id:4, value:8}].
How do I get the position of the array element with id === 3(3rd element) in the arrayElements variable besides using loop?
thanks.
You have to loop at one point. But you can abstract it to look like you're not looping
function indexOfCallback(arr, callback, startIndex) {
if (typeof startIndex == 'undefined') {
startIndex = 0;
}
for(var i=startIndex; i < arr.length; i ++) {
if (callback(arr[i])) {
return i;
}
}
return -1;
}
var array = [{id:1, value:5},{id:2, value:6},{id:3, value:7},{id:4, value:8}];
// Search on id === 3
console.log(indexOfCallback(array, function(obj){
return obj.id === 3;
}));
// Search on value === 6
console.log(indexOfCallback(array, function(obj){
return obj.value === 6;
}));
As mentioned by Anthony, this is proposed for ECMAScript 6. Here's the more complete polyfill https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex
if (!Array.prototype.findIndex) {
Array.prototype.findIndex = function(predicate) {
if (this == null) {
throw new TypeError('Array.prototype.find called on null or undefined');
}
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
var list = Object(this);
var length = list.length >>> 0;
var thisArg = arguments[1];
var value;
for (var i = 0; i < length; i++) {
value = list[i];
if (predicate.call(thisArg, value, i, list)) {
return i;
}
}
return -1;
};
}
console.log(array.findIndex(function(obj){
return obj.id === 3;
}));
arrayElements.map(o => o.id).indexOf(3);
Notes:
Possibly slower than a loop because transforms whole array prior to
search. But with high-level languages like Javascript, you never
know.
Infinitely more readable than a loop.
IE compatible (unlike findIndex as of 2017).
In an array like this, you cant access elements by id. So using a loop is the best solution you have. However, depending on your use case you could also consider using an object instead of an array for direct access.
var container = { 1: {id:1, value:5}, 2: {id:2, value:6}, 3: {id:3, value:7} }
const arrayElements = [
{ id: 1, value: 5 },
{ id: 2, value: 6 },
{ id: 3, value: 7 },
{ id: 4, value: 8 }
]
console.log(arrayElements.findIndex((item) => item.id === 3))
You can use an array filter but I think that you will get a better solution using a loop.
var array = [{id:1, value:5},{id:2, value:6},{id:3, value:7},{id:4, value:8}];
var result = array.filter(condition);
function condition(value, index){
if (value.id === 3) return index;
}
console.log(result);
I wrote a function for you that you can use get the job done, but it uses a loop:
var yourObjArray = [{id:1, value:5},{id:2, value:6},{id:3, value:7},{id:4, value:8}];
function objArrayIndex(objArray){
for(var i = 0; i < objArray.length; i++){
if(objArray[i]['id'] == 3){
return i;
}
}
return -1;
}
console.log(objArrayIndex(yourObjArray));

Listing keys containing a given string?

Given data such as :
var people = [
{ 'myKey': 'John Kenedy', 'status': 1 },
{ 'myKey': 'Steeven Red', 'status': 0 },
{ 'myKey': 'Mary_Kenedy', 'status': 3 },
{ 'myKey': 'Carl Orange', 'status': 0 },
{ 'myKey': 'Lady Purple', 'status': 0 },
... // thousands more
];
How to efficiently get the list of all objects which contains in myKey the string Kenedy ?
http://jsfiddle.net/yb3rdhm8/
Note: I currently use str.search() :
The search("str") returns the position of the match. Returns -1 if no match is found.
to do as follow :
var map_partial_matches = function(object, str){
var list_of_people_with_kenedy = [] ;
for (var j in object) {
if (object[j]["myKey"].search(str) != -1) {
object[j].presidentName = "yes"; // do something to object[j]
list_of_people_with_kenedy.push({ "people": object[j]["myKey"] }); // add object key to new list
}
} return list_of_people_with_kenedy;
}
map_partial_matches(people, "Kenedy");
I could do the same using str.match() :
str.match() returns the matches, as an Array object. Returns null if no match is found.
It works anyway, but I have no idea if it's efficient or completely dump.
You can use filter():
var filtered = people.filter(function (item) {
if (item.myKey.indexOf("Kenedy") != -1)
return item;
});
You can also checkout Sugar.js
In order to search your unsorted object you need to get through all of it's properties - So I'd say a simple loop with an indexOf will be pretty much the best you can go:
var foundItems = [];
for(var i = 0; i < people.length ;i++)
{
if(people[i].myKey.indexOf('Kenedy') > -1)
foundItems.push(people[i]]);
}
Maybe you can tweak it up a little, but it's pretty much the best you can get.
You can write a basic function that uses filter to return an array of matches based on a key and value:
function find(arr, key, val) {
return arr.filter(function (el) {
return el[key].indexOf(val) > -1;
});
}
var result = find(people, 'myKey', 'Kenedy');
Alternatively use a normal for...loop:
function find(arr, key, val) {
var out = [];
for (var i = 0, l = arr.length; i < l; i++) {
if (arr[i][key].indexOf(val) > -1) {
out.push(arr[i]);
}
}
return out;
}
DEMO
Does the Object Contain a Given Key?
function hKey(obj, key) {
arr = [];
// newarr =[];
for(el in obj){
arr.push(el)
} //return arr;
for(i=0; i<arr.length; i++){
name = arr[i]
} if(name == key) {
return true;
}else {
return false;
}
}
console.log(hKey({ a: 44, b: 45, c: 46 }, "c"))

remove item from array using its name / value

I have the following array
var countries = {};
countries.results = [
{id:'AF',name:'Afghanistan'},
{id:'AL',name:'Albania'},
{id:'DZ',name:'Algeria'}
];
How can I remove an item from this array using its name or id ?
Thank you
Created a handy function for this..
function findAndRemove(array, property, value) {
array.forEach(function(result, index) {
if(result[property] === value) {
//Remove from array
array.splice(index, 1);
}
});
}
//Checks countries.result for an object with a property of 'id' whose value is 'AF'
//Then removes it ;p
findAndRemove(countries.results, 'id', 'AF');
Array.prototype.removeValue = function(name, value){
var array = $.map(this, function(v,i){
return v[name] === value ? null : v;
});
this.length = 0; //clear original array
this.push.apply(this, array); //push all elements except the one we want to delete
}
countries.results.removeValue('name', 'Albania');
Try this:
var COUNTRY_ID = 'AL';
countries.results =
countries.results.filter(function(el){ return el.id != COUNTRY_ID; });
Try this.(IE8+)
//Define function
function removeJsonAttrs(json,attrs){
return JSON.parse(JSON.stringify(json,function(k,v){
return attrs.indexOf(k)!==-1 ? undefined: v;
}));}
//use object
var countries = {};
countries.results = [
{id:'AF',name:'Afghanistan'},
{id:'AL',name:'Albania'},
{id:'DZ',name:'Algeria'}
];
countries = removeJsonAttrs(countries,["name"]);
//use array
var arr = [
{id:'AF',name:'Afghanistan'},
{id:'AL',name:'Albania'},
{id:'DZ',name:'Algeria'}
];
arr = removeJsonAttrs(arr,["name"]);
You can delete by 1 or more properties:
//Delets an json object from array by given object properties.
//Exp. someJasonCollection.deleteWhereMatches({ l: 1039, v: '3' }); ->
//removes all items with property l=1039 and property v='3'.
Array.prototype.deleteWhereMatches = function (matchObj) {
var indexes = this.findIndexes(matchObj).sort(function (a, b) { return b > a; });
var deleted = 0;
for (var i = 0, count = indexes.length; i < count; i++) {
this.splice(indexes[i], 1);
deleted++;
}
return deleted;
}
you can use delete operator to delete property by it's name
delete objectExpression.property
or iterate through the object and find the value you need and delete it:
for(prop in Obj){
if(Obj.hasOwnProperty(prop)){
if(Obj[prop] === 'myValue'){
delete Obj[prop];
}
}
}
This that only requires javascript and appears a little more readable than other answers.
(I assume when you write 'value' you mean 'id')
//your code
var countries = {};
countries.results = [
{id:'AF',name:'Afghanistan'},
{id:'AL',name:'Albania'},
{id:'DZ',name:'Algeria'}
];
// solution:
//function to remove a value from the json array
function removeItem(obj, prop, val) {
var c, found=false;
for(c in obj) {
if(obj[c][prop] == val) {
found=true;
break;
}
}
if(found){
delete obj[c];
}
}
//example: call the 'remove' function to remove an item by id.
removeItem(countries.results,'id','AF');
//example2: call the 'remove' function to remove an item by name.
removeItem(countries.results,'name','Albania');
// print our result to console to check it works !
for(c in countries.results) {
console.log(countries.results[c].id);
}
it worked for me..
countries.results= $.grep(countries.results, function (e) {
if(e.id!= currentID) {
return true;
}
});
You can do it with _.pullAllBy.
var countries = {};
countries.results = [
{id:'AF',name:'Afghanistan'},
{id:'AL',name:'Albania'},
{id:'DZ',name:'Algeria'}
];
// Remove element by id
_.pullAllBy(countries.results , [{ 'id': 'AL' }], 'id');
// Remove element by name
// _.pullAllBy(countries.results , [{ 'name': 'Albania' }], 'name');
console.log(countries);
.as-console-wrapper {
max-height: 100% !important;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Maybe this is helpful, too.
for (var i = countries.length - 1; i--;) {
if (countries[i]['id'] === 'AF' || countries[i]['name'] === 'Algeria'{
countries.splice(i, 1);
}
}
The accepted answer is problematic as it attaches a function to the Array prototype. That function will show up whenever you run thru the array using a for loop:
for (var key in yourArray) {
console.log(yourArray[key]);
}
One of the values that will show up will be the function. The only acceptable way to extend base prototypes (although it is generally discouraged as it pollutes the global space) is to use the .defineProperty method:
Object.defineProperty(Object.prototype, "removeValue", {
value: function (val) {
for (var i = 0; i < this.length; i++) {
if (this[i] === val) {
this.splice(i, 1);
i--;
}
}
return this;
},
writable: true,
configurable: true,
enumerable: false
});

Categories