I have an array of objects that looks something like
{
"foo":[
{
"bar":"boo"
},
{
"baz":"bang"
}
]
}
I want to update baz with a new value but I cannot work out how to merge both these objects?
I tried something like Object.assign({}, foo,{baz: 'beep'})
But this did not work?
foo is an Array of objects to replace it with new value, try the following:
var obj = { "foo":[ { "bar":"boo" }, { "baz":"bang" } ] };
var index = obj.foo.findIndex((o) =>Object.keys(o).includes("baz"));
if(index != -1)
Object.assign(obj.foo[index], {baz: 'beep'});
console.log(obj);
Assuming you don't necessarily know the array index of the element you're trying to modify, you'll need to search through that array to find it -- for example using Array.find():
let quux = {
"foo":[
{
"bar":"boo"
},
{
"baz":"bang"
}
]
}
quux.foo.find(
(obj) => {
return obj.baz === "bang"
}
).baz="beep";
console.log(quux);
// This mutates the original object; if you need a clone wrap this in an Object.assign as shown in other answers
(Arrays of objects can be inconvenient for this reason; you may be better off with an object of objects, so there's an ID for each.)
If you're trying to create a modified copy of foo, use Array.prototype.map:
const foo = [
{
"bar":"boo"
},
{
"baz":"bang"
}
];
const newFoo = foo.map(value => {
if('baz' in value) return Object.assign({}, value, {a: 'b'});
return value;
});
console.log(newFoo);
Related
I have 2 arrays. one is costHeadArray which is as
[
{
"label":"Flight",
"value":"179daf5f-2f89-1d12-40a2-e91a6a732774"
}
]
I am iterating response. My object value is as
{
taxInvoiceId: "b1b4d9ec-f20c-4a33-94c1-af7589e7b15a",
enquiryId: "3db0b4a8-5ab1-4c31-861a-73df36205716",
costHeadId: "179daf5f-2f89-1d12-40a2-e91a6a732774",
costSheetId: "01edd4a1-f1ad-a836-3a19-3a28271f1b57",
...
}
Now in same iteration, I need to check if costHeadArray value matches value in object. costHeadArray can have multiple json objects. only if value in costHeadArray matches with object then i need to enable flag. I tried using includes but it dont works . might be I am doing something wrong
My code
this.airInvoiceService.getTaxInvoiceLog(this.enquiryId).subscribe(
response => {
this.taxInvoiceLogs.unshift(...response);
for(const a of response) {
// {taxInvoiceId: "b1b4d9ec-f20c-4a33-94c1-af7589e7b15a", enquiryId: "3db0b4a8-5ab1-4c31-861a-73df36205716", enquiryRefId: "MTPL-2021-000074", costHeadId: "179daf5f-2f89-1d12-40a2-e91a6a732774", costSheetId: "01edd4a1-f1ad-a836-3a19-3a28271f1b57", …}
console.log(a);
//[{"label":"Flight","value":"e9bf7aa2-c730-8175-1cec-afcd239b0dff"}]
console.log(JSON.stringify(this.costHeadArray));
console.log(a.costHeadId);
if (Object.values(a).includes(this.costHeadArray)){
console.log('Gokul');
}
if (this.costHeadArray.includes(a.costHeadId)) {
console.log('Sam');
this.hideForm = true;
}
}
I have write simple script for you, please have a look, I hope it will help you
let costHeadArray = [
{
"label":"Flight",
"value":"179daf5f-2f89-1d12-40a2-e91a6a732774"
}
];
let myObject = {
taxInvoiceId: "b1b4d9ec-f20c-4a33-94c1-af7589e7b15a",
enquiryId: "3db0b4a8-5ab1-4c31-861a-73df36205716",
costHeadId: "179daf5f-2f89-1d12-40a2-e91a6a732774",
costSheetId: "01edd4a1-f1ad-a836-3a19-3a28271f1b57",
}
let hasCostHeadValue = costHeadArray.find(o => o.value == myObject.costHeadId) != null;
console.log(hasCostHeadValue);
///////////////////////////////////////////////////////////////////////////////////
Update your method like this.
this.airInvoiceService.getTaxInvoiceLog(this.enquiryId).subscribe(
response => {
this.taxInvoiceLogs.unshift(...response);
for(const a of response) {
// {taxInvoiceId: "b1b4d9ec-f20c-4a33-94c1-af7589e7b15a", enquiryId: "3db0b4a8-5ab1-4c31-861a-73df36205716", enquiryRefId: "MTPL-2021-000074", costHeadId: "179daf5f-2f89-1d12-40a2-e91a6a732774", costSheetId: "01edd4a1-f1ad-a836-3a19-3a28271f1b57", …}
console.log(a);
//[{"label":"Flight","value":"e9bf7aa2-c730-8175-1cec-afcd239b0dff"}]
console.log(JSON.stringify(this.costHeadArray));
console.log(a.costHeadId);
let hasCostHeadValue = this.costHeadArray.find(o => o.value == a.costHeadId) != null;
if(hasConstHeadValue){
} else {
}
// if (Object.values(a).includes(this.costHeadArray)){
// console.log('Gokul');
// }
// if (this.costHeadArray.includes(a.costHeadId)) {
// console.log('Sam');
// this.hideForm = true;
//}
}
Array.includes is comparing the array items by reference, not by value, thus:
For the array const values = [ {value: 1}, { value: 2} ]
values.includes(values[0]) will return true, because it re-uses the same {value:1}-object as the array and both objects have same reference ID.
values.includes({value: 1}) will return false, because the objects have the same content but different references.
You can use Array.findIndex instead:
const search = {value: 1};
const includes = values.findIndex(item => item.value === search.value) >= 0;
I have an object array containing one property call name like this
var nameArr = [
{
"name":"john"
},
{
"name":"carl"
},
{
"name":"peter"
}
]
I have a another array called ageArr and it only contain property called age
var ageArr = [
{
"age":"22"
},
{
"age":"21"
},
{
"age":"32"
}
]
i want to concat these array and end result should result like this
var result = [
{
"age":"22",
"name":"john"
},
{
"age":"21",
"name":"carl"
},
{
"age":"32",
"name":"peter"
}
]
note that length of the both arrays always equal and dynamic. Is there any way i can do this without looping these array inside one another. Thank you.
You can use Object.assign() and map() and return new array.
var nameArr = [{"name":"john"},{"name":"carl"},{"name":"peter"}]
var ageArr = [{"age":"22"},{"age":"21"},{"age":"32"}]
var result = nameArr.map(function(e, i) {
return Object.assign({}, e, ageArr[i])
})
console.log(result)
Single forEach() function is enough.
var nameArr=[{name:"john"},{name:"carl"},{name:"peter"}],
ageArr=[{age:"22"},{age:"21"},{age:"32"}];
nameArr.forEach((v,i) => v.age = ageArr[i].age)
console.log(nameArr);
You can use the following code snippet.
var result = nameArr.map(function( obj, index ) {
var res = ageArr[index];
res.name = obj.name;
return res;
});
In the map, you can easily use
jQuery.extend()
to create a merge of two same index object.
Using LoDash to map over an object:
_.map(items, (item) = > {
if (Array.isArray(item)) {
// don't include this in final object
}
return _.assign({
foo: "bar"
}, item);
});
Wondering what my best tactic is for not including an object in the returned, mapped, object if the current object is an array?
You may use reduce which works perfectly for your case:
var items = [{a: 1}, ["asd"], {b: 2}];
var result = _.reduce(items, (res, item) => {
if (!Array.isArray(item)) {
_.assign(res, item);
}
return res;
}, {foo: "bar"});
See jsbin.
Another (and IMO a cleaner) solution is to use chaining:
results = _(items).reject(_.isArray).map(function(item) {
....
}).value()
I would expect a map function to always output the same keys as the input. The values maybe modified, but the keys remain the same.
There are other functions you can use to change the set of items like filter or some kind of aggregate or reduce.
This... just assign an empty object if item is an array, otherwise assign item:
_.map(items, (item) = > {
return _.assign({
foo: "bar"
}, Array.isArray(item)?{}:item);
});
Here's a little fiddle without the new anonymous function syntax: https://jsfiddle.net/xurm6vrr/1/
With an array of objects in a form like this:
[
{
1429={
{
8766={...},
8483={...},
7345={...}
}
}
},
{
9041={...}
}
]
how could i get back an array like this?:
[1429, 9041]
If the array of objects would be in another structure this code would work:
var obj = {
"5": "some",
"8": "thing"
};
var keys = $.map(obj, function (value, key) {
return key;
});
console.log(keys);
That would return [5, 8]. But in my example it just would return the indexes [0,1]
Even if I wouldn't know the depth of the object - is it possible to get the values on that level? I dont need the indexes, I need those values. I couldn't find anything about it so far. Any tips for me maybe?
P.S.: I know that i could work out something with these keys and a loop, but I'm just asking for a simplier way to do it.
Regards
you are looking for the keys in a json object, you can get them this way:
Object.keys(obj);
for the object example:
var obj = {
"5": "some",
"8": "thing"
};
you will get:
["5","8"]
for an array of object of this type:
var arrayObject = [{},{},{}];
you can use a map and get the keys:
var keys = arrayObject.map(function(k){
return Object.keys(k);
});
keys is an array of arrays of keys. Example, for the following object (similar to your data structure):
var l= [
{
1429:{
8766: "test",
8483:"test",
7345: "test"
}
},
{
9041: "test"
}
];
you will get:
[["1429"],["9041"]]
apply concat and you will get what you are looking for. Here how to apply concat in the case of multiple arrays.
var arrayOfKeys = [].concat.apply([], keys);
now you will get:
["1429","9041"];
In your specific case you could use
var keys = [];
root.forEach(function(v) { keys = keys.concat(Object.keys(v)); });
If instead you have a tree of arrays and you want the keys of all other objects instead (but not recursing into objects) then a simple recursive function would do it:
function topKeys(x) {
if (x && x.constructor === Array) {
var result = [];
x.forEach(function(item) {
result = result.concat(topKeys(item));
});
return result;
} else if (typeof x === "object") {
return Object.keys(x);
} else {
return [];
}
}
Consider:
var object = {
foo: {},
bar: {},
baz: {}
}
How would I do this:
var first = object[0];
console.log(first);
Obviously, that doesn’t work because the first index is named foo,
not 0.
console.log(object['foo']);
works, but I don’t know it’s named foo. It could be named anything. I just want the first.
Just for fun this works in JS 1.8.5
var obj = {a: 1, b: 2, c: 3};
Object.keys(obj)[0]; // "a"
This matches the same order that you would see doing
for (o in obj) { ... }
If you want something concise try:
for (first in obj) break;
alert(first);
wrapped as a function:
function first(obj) {
for (var a in obj) return a;
}
they're not really ordered, but you can do:
var first;
for (var i in obj) {
if (obj.hasOwnProperty(i) && typeof(i) !== 'function') {
first = obj[i];
break;
}
}
the .hasOwnProperty() is important to ignore prototyped objects.
This will not give you the first one as javascript objects are unordered, however this is fine in some cases.
myObject[Object.keys(myObject)[0]]
If the order of the objects is significant, you should revise your JSON schema to store the objects in an array:
[
{"name":"foo", ...},
{"name":"bar", ...},
{"name":"baz", ...}
]
or maybe:
[
["foo", {}],
["bar", {}],
["baz", {}]
]
As Ben Alpert points out, properties of Javascript objects are unordered, and your code is broken if you expect them to enumerate in the same order that they are specified in the object literal—there is no "first" property.
for first key of object you can use
console.log(Object.keys(object)[0]);//print key's name
for value
console.log(object[Object.keys(object)[0]]);//print key's value
There is no way to get the first element, seeing as "hashes" (objects) in JavaScript have unordered properties. Your best bet is to store the keys in an array:
var keys = ["foo", "bar", "baz"];
Then use that to get the proper value:
object[keys[0]]
ES6
const [first] = Object.keys(obj)
Using underscore you can use _.pairs to get the first object entry as a key value pair as follows:
_.pairs(obj)[0]
Then the key would be available with a further [0] subscript, the value with [1]
I had the same problem yesterday. I solved it like this:
var obj = {
foo:{},
bar:{},
baz:{}
},
first = null,
key = null;
for (var key in obj) {
first = obj[key];
if(typeof(first) !== 'function') {
break;
}
}
// first is the first enumerated property, and key it's corresponding key.
Not the most elegant solution, and I am pretty sure that it may yield different results in different browsers (i.e. the specs says that enumeration is not required to enumerate the properties in the same order as they were defined). However, I only had a single property in my object so that was a non-issue. I just needed the first key.
You could do something like this:
var object = {
foo:{a:'first'},
bar:{},
baz:{}
}
function getAttributeByIndex(obj, index){
var i = 0;
for (var attr in obj){
if (index === i){
return obj[attr];
}
i++;
}
return null;
}
var first = getAttributeByIndex(object, 0); // returns the value of the
// first (0 index) attribute
// of the object ( {a:'first'} )
To get the first key of your object
const myObject = {
'foo1': { name: 'myNam1' },
'foo2': { name: 'myNam2' }
}
const result = Object.keys(myObject)[0];
// result will return 'foo1'
Based on CMS answer. I don't get the value directly, instead I take the key at its index and use this to get the value:
Object.keyAt = function(obj, index) {
var i = 0;
for (var key in obj) {
if ((index || 0) === i++) return key;
}
};
var obj = {
foo: '1st',
bar: '2nd',
baz: '3rd'
};
var key = Object.keyAt(obj, 1);
var val = obj[key];
console.log(key); // => 'bar'
console.log(val); // => '2nd'
My solution:
Object.prototype.__index = function(index)
{
var i = -1;
for (var key in this)
{
if (this.hasOwnProperty(key) && typeof(this[key])!=='function')
++i;
if (i >= index)
return this[key];
}
return null;
}
aObj = {'jack':3, 'peter':4, '5':'col', 'kk':function(){alert('hell');}, 'till':'ding'};
alert(aObj.__index(4));