Iterate over an object and add new attributes - javascript

So I have an object. I want to iterate over it and return same object but with additional attributes. I have done the following but it returns old data.
_.each(data, function(item) {
_.extend(item, {name: item.first});
});
Ok i have even tried, still no luck
_.each(data, function (item){
item.name = item.first;
return item;
});

You can better use Array.map for this
var newData = data.map(function(i){
i['name'] = i.first;
return i;
})

var data = {
a : { first : 'albert'},
b : { first : 'bob' },
c : { first : 'charle'}
};
for ( var item in data ) {
data[item].name = data[item].first;
}
If you want to change an object you should not "return" it, because is nonsense, javascript doesn't copy object anyway, return will give a link to the same data object, and if you change this object will change data too, if you really nead a diferent object, you will need do a deep copy of your object.
Exemple:
a = {name:'albert'};
b = a;
b.name = 'bob';
console.log(a);
will show { name: 'bob' }

That is beacause extend copies the second object's properties in the first: http://underscorejs.org/#extend
Im not sure what you want, but won't this fix it?
_.each(data, function(item) {
//set item.first property on item.name
item.name = item.first;
});
//var data is still the same array with same objects, but all the objects inside are updated.
based on your comment
here you go, what you want:
var yourNewArray = data.map(function(item){
//clone item so you dont have reference to object in dat array
var newItem = _.clone(item);
//set property on another property
newItem.name = newItem.first;
return newItem;
}
another way
Another way if you only want that specific proprety as object array:
var yourNewArray = data.map(function(item){
return { name : item.first}; //return object with property name, with value from original object.first property
}
Remember: an array contains an list of object References. So you cant simply change the objects, you need to clone them so you don't change the original array.

Related

how to insert new object in node js array if key not exist

I want to create data structure like that.
Var ans =[{"b":[1,2]},{"g":[100,2]}]
I want to create a new object within list if key not exists in list ans.
Else if key exists in one object of ans list then I want to add new values into the object of ans list
For Example:
Example 1) new data c:{2000}
then
Var ans =[{"b":[1,2]},{"g":[100,2]},{c:[2000]}]
Example 2) new data g:{50}
then
Var ans =[{"b":[1,2]},{"g":[100,2,500]},{c:[2000]}]
I am a beginner in node js, understand array, object concept, but not getting exact logic!
Thanks!
You can try following:
Logic
Filter array based on key
Check if object with mentioned key exists or not.
If yes, push value to this array.
If not, create a dummy object and push this object to original array.
Correction, when you do .push({key: value}), key will be considered as string.
Alternates
If you are using ES6, .push({ [key] : value })
Create a dummy object var o = {}. Set key and value to it o[key] = value and push this object.
Optimisations
Instead of setting value like obj[key] = value, since we will be operating on arrays, try obj[key] = [].concat(value). This will enable you to pass value as number or array of values.
Instead of checking the existence of value in .filter, try Array.isArray to check if value exists and is of type array.
Custom function
function checkAndPush(array, key, value) {
var filteredList = array.filter(function(o) {
return Array.isArray(o[key]);
});
filteredList.length > 0 ? filteredList[0][key].push(value) : array.push({
[key]: [].concat(value)
});
return array;
}
var ans =[{"b":[1,2]},{"g":[100,2]}]
console.log(checkAndPush(ans, "c", [2,3]))
console.log(checkAndPush(ans, "c", 4));
Prototype function
Array.prototype.checkAndPush = function(key, value) {
var filteredList = this.filter(function(o) {
return Array.isArray(o[key]);
});
var dummy = {}
dummy[key] = [].concat(value)
filteredList.length > 0 ? filteredList[0][key].push(value) : this.push(dummy);
// or ES6: this.push({ [key]: [].concat(value) })
return this;
}
var ans =[{"b":[1,2]},{"g":[100,2]}]
console.log(ans.checkAndPush("c", [2,3]))
console.log(ans.checkAndPush("c", 4));
If you are dealing with objects as your values
ans[key] = ans[key] || []
ans[key].push(value)
Note, this works because your values will be an array. If they could be primatives then you would use hasOwnProperty to check.
if (ans.hasOwnProperty(key)) {
// Add this to your key somehow
} else {
// initialize the key with your value
}
Node.js is nothing but a library built on javascript. You can do anything using javascript type of progmming. However push and pop method should be able to help you to deal with nodejs array.
ans[key].push(value)

Is it necessary to create nested jSON objects before using it?

I think I've seen how to create a JSON object without first preparing it. This is how i prepare it:
obj = {
0:{
type:{}
},
1:{},
2:{}
};
Now I think I can insert a value like: obj.0.type = "type0"; But I'd like to create it while using it: obj['0']['type'] = "Type0";.
Is it possible, or do I need to prepare it? I'd like to create it "on the fly"!
EDIT
I'd like to create JS object "On the fly".
var obj = {};
obj.test = "test"; //One "layer" works fine.
obj.test.test = "test" //Two "layers" do not work... why?
obj = {
0:{
type:{}
},
1:{},
2:{}
};
Now i think i can insert value like: obj.0.type = "type0";
I guess you mean "assign" a value, not "insert". Anyway, no, you can't, at least not this way, because obj.0 is invalid syntax.
But I'd like to create it while using it: obj['0']['type'] = "Type0";
That's fine. But you need to understand you are overwriting the existing value of obj[0][type], which is an empty object ({}), with the string Type0. To put it another way, there is no requirement to provide an initialized value for a property such as type in order to assign to it. So the following would have worked equally well:
obj = {
0:{},
1:{},
2:{}
};
Now let's consider your second case:
var obj = {};
obj.test = "test"; //One "layer" works fine.
obj.test.test = "test" //Two "layers" do not work... why?
Think closely about what is happening. You are creating an empty obj. You can assign to any property on that object, without initializing that property. That is why the assignment to obj.test works. Then in your second assignment, you are attempting to set the test property of obj.test, which you just set to the string "test". Actually, this will work--because strings are objects that you can set properties on. But that's probably not what you want to do. You probably mean to say the previous, string value of obj.test is to be replaced by an object with its own property "test". To do that, you could either say
obj.test = { test: "test" };
Or
obj.test = {};
obj.test.test = "test";
You are creating a plain object in JavaScript and you need to define any internal attribute before using it.
So if you want to set to "Type0" an attribute type, inside an attribute 0 of an object obj, you cannot simply:
obj['0']['type'] = "Type0";
You get a "reference error". You need to initialize the object before using it:
var obj = {
0: {
type: ""
}
};
obj['0']['type'] = "Type0";
console.log(obj['0']['type']);
You could create your own function that takes key as string and value and creates and returns nested object. I used . as separator for object keys.
function create(key, value) {
var obj = {};
var ar = key.split('.');
ar.reduce(function(a, b, i) {
return (i != (ar.length - 1)) ? a[b] = {} : a[b] = value
}, obj)
return obj;
}
console.log(create('0.type', 'type0'))
console.log(create('lorem.ipsum.123', 'someValue'))
Is it necessary to create nested objects before using it?
Yes it is, at least the parent object must exist.
Example:
var object = {};
// need to assign object[0]['prop'] = 42;
create the first property with default
object[0] = object[0] || {};
then assign value
object[0]['prop'] = 42;
var object = {};
object[0] = object[0] || {};
object[0]['prop'] = 42;
console.log(object);
Create object with property names as array
function setValue(object, keys, value) {
var last = keys.pop();
keys.reduce(function (o, k) {
return o[k] = o[k] || {};
}, object)[last] = value;
}
var object = {};
setValue(object, [0, 'prop'], 42);
console.log(object);

Find index of object in array by key

I have an array of objects like so
myobj= [{"item1" : info in here},{"item2" : info in here}, {"item3" : info in here}]
I'm trying to modify one, but I only know its key. I need to pinpoint the item1 object so I can change its value (the values are random and I don't know them, so I can't rely upon them).
If I could just get the index of the item it would be pretty easy: myobj[index].value = "newvalue".
Maybe using the index isn't the best way, so if it isn't, I'm open to other ideas.
I was thinking I could try something like
myobj.objectVar
Where objectVar is the key I'm being passed (item1, for example), however this does not work, possibly because it's a variable? Is it possible to use a variable like this maybe?
If it helps, I'm using underscore.js as well.
Your guess at a solution doesn't work because you're not accessing the individual objects, you're accessing an array of objects, each of which has a single property.
To use the data in the format you've got now, you need to iterate over the outer array until you find the object that contains the key you're after, and then modify its value.
myobj= [{"item1" : info in here},{"item2" : info in here}, {"item3" : info in here}]
function setByKey(key, value) {
myObj.forEach(function (obj) {
// only works if your object's values are truthy
if (obj[key]) {
obj[key] = value;
}
});
}
setByKey('item1', 'new value');
Of course, the far better solution is to stop using an array of single-property objects, and just use one object with multiple properties:
myobj= {"item1" : info in here, "item2" : info in here, "item3" : info in here};
Now, you can simply use myObject.item1 = "some new value" and it will work fine.
You can write a function like,
function getElementsHavingKey(key) {
var objectsHavingGivenKey = [];
//loop through all the objects in the array 'myobj'
myobj.forEach(function(individualObject) {
//you can use 'hasOwnProperty' method to find whether the provided key
// is present in the object or not
if(individualObject.hasOwnProperty(key)) {
// if the key is present, store the object having the key
// into the array (many objects may have same key in it)
objectsHavingGivenKey.push(individualObject);
}
});
// return the array containing the objects having the keys
return objectsHavingGivenKey;
}
If you only want to get the index of elements having the given key
You can do something like this,
function getIndexesOfElementsHavingKey(key) {
var objectsHavingGivenKey = [];
//loop through all the objects in the array 'myobj'
myobj.forEach(function(individualObject, index) {
//you can use 'hasOwnProperty' method to find whether the provided key
// is present in the object or not
if(individualObject.hasOwnProperty(key)) {
//push index of element which has the key
objectsHavingGivenKey.push(index);
}
});
// returns the array of element indexes which has the key
return objectsHavingGivenKey;
}
Try this code:
function changeObj( obj, key, newval )
{
for( var i=0, l=obj.length; i<j; i++)
{
if( key in obj[i] )
{
obj[i] = newval;
return;
}
}
}
var myObjArray= [{"item1" : "info in here"},{"item2" : "info in here"}, {"item3" : "info in here"}]
To find and add new value to the object inside an array:
myObjArray.forEach(function(obj) {
for(var key in obj) {
// in case you're matching key & value
if(key === "item1") {
obj[key] = "update value";
// you can even set new property as well
obj.newkey = "New value";
}
}
});
You can access objects the same using their index, even the object inside the original object.
Is this kind of what your looking for:
var otherObj = [{"oitem":"oValue"}];
var myobj= [{"item1" : otherObj},{"item2" : "2"}, {"item3" : "tesT"}];
myobj[0].item1[0].oitem = "newvalue";
alert(myobj[0].item1[0].oitem);

Getting a reference to an array element

While I realize that an array, as a non-primitive data type, is handled by references in JavaScript, not by value, any particular element of that array could be a primitive data type, and I assume then that it is not assigned by reference.
I'd like to know how to get a reference to an individual element in an array so that I don't have to keep referring to the array and the index number while changing that element?
i.e.
var myElement=someArray[4]
myElement=5
//now someArray[4]=5
Am I misinterpreting various docs that imply but do not explicitly state that this is not the intended behavior?
You can make a copy of an array element, but you can't create a value that serves as an alias for an array property reference. That's also true for object properties; of course, array element references are object property references.
The closest you could get would be to create an object with a setter that used code to update your array. That would look something like:
var someArray = [ ... whatever ... ];
var obj = {
set element5(value) {
someArray[5] = value;
}
};
Then:
obj.element5 = 20;
would update someArray[5]. That is clearly not really an improvement over someArray[5] = 20.
edit — Now, note that if your array element is an object, then making a copy of the element means making a copy of the reference to the object. Thus:
var someArray = [ { foo: "hello world" } ];
var ref = someArray[0];
Then:
ref.foo = "Goodbye, cruel world!";
will update the "foo" property of the object referenced by someArray[0].
You can always pass around a closure to update this:
var myUpdater = function(x) {
someArray[4] = x;
}
myUpdater(5);
If you want read/write capabilities, box it:
var makeBox = function(arr, n) {
return {
read: function() { return arr[n]; },
write: function(x) { arr[n] = x; }
};
}
// and then:
var ptr = makeBox(someArray, 4);
ptr.read(); // original
ptr.write(newValue);
someArray[4]; // newValue

how to filter object in javascript

I an working in javascript and stuck in understanding the objects.
Here is my scenario.
I have an object which in turn has multiple objects in it like.
data {
"aa" : object
"bb" : object
"cc" : object
}
//expanding aa bb and cc
aa {
name : "a"
type : "static"
value : "123"
}
bb {
name : "b"
type : "dyn"
value : "343"
}
cc {
name : "c"
type : "dyn"
value : "545"
}
Now what I want to achieve is that i have an object which should have those objects that have type = "dyn"
so i want to have a reqdata object like this
reqdata {
"bb" : object
"cc" : object
}
I have written a code to do this but it is not working as my reqdata has all the data.
var reqData = $.each (data, function(key, d){
if (type === "dyn")
return d;
});
Can any one guide me what the proper and efficient way of looping through the object.
Thanks any help and guidance will be appreciated
You need to create a new object, test the type property, and assign the current sub-object to the new one if the type is what you want.
// v--- Holds the results
var newObj = {};
// v--- The current sub-object
$.each(data, function(key, obj){
if (obj.type === "dyn") // <-- Test its `type` property
newObj[key] = obj; // <-- and assign to `newObj` if it matches
});
You should note that you're not making a copy of obj when you assign it to newObj. You're making a copy of a reference to obj.
This means that data and newObj share the same objects. Changes made via data are observable from newObj, and vice versa.
If you're used to functional programming, you can write your own filter function for objects:
function oFilter (obj, f) {
var result = {};
for (var x in obj) {
if (
obj.hasOwnProperty(x) &&
f(x,obj[x])
) {
result[x] = obj[x];
}
}
return result;
}
Then it'd be as you expected:
var reqData = oFilter(data, function(key,d){
if (d.type === "dyn") return true;
return false;
});
Similarly for map:
function oMap (obj, f) {
var result = {};
for (var x in obj) {
if (obj.hasOwnProperty(x)) {
result[x] = f(x,obj[x]);
}
}
return result;
}
Reduce doesn't make sense for objects though.
Shorter.
$(data).each( function(){
if(this.type === 'dyn'){ doStuff(this); }
} );
Now, IMO, constructor name is closer to type in JS. I'd build those objects with a function constructor names 'Dyn' and check <instance>.constructor.name for 'Dyn' but you would have to normalize for IE<=8 which involves parsing <instance>constructor.toString() so perhaps more trouble than it's worth.
But if you want to understand JS objects. Ditch the jQuery until you do. Learn how to use:
for(var x in object){
console.log('propertyLabel:' +x+', property:' + object[x]+'\n');
}
Then go back to understanding how jQuery itself works. Lots of juicy stuff under the hood there.

Categories

Resources