Angular 2 add key and value to each array object - javascript

I have array of objects :
array = [
{name: 'name'},
{name: 'name'},
{name: 'name'},
{name: 'name'},
]
I want to add key: '123' to each of them so it would be :
array = [
{name: 'name', key: '123'},
{name: 'name', key: '123'},
{name: 'name', key: '123'},
{name: 'name', key: '123'},
]
What I've tryed :
checked = false;
this.editObj.forEach(item => item.push(this.checked))
ERROR : item.push is not a function.
But it isn't working. How to do it in the right way ?

const arr = [
{name: 'name'},
{name: 'name'},
{name: 'name'},
{name: 'name'},
]
const arr2 = arr.map(x => ({...x , key: '123'}));

You can try with creating custom dictionary
array = [
{name: 'name'},
{name: 'name'},
{name: 'name'},
{name: 'name'},
]
var dict = []; // create an empty dictionary
for (i = 0; i < array.length; i++) {
dict.push({
key: "123",
value: array[i].name
});
}
console.log(dict);

you should do :
this.editObj.forEach(item => item["key"]= "123");
console.log(this.editObj);

Your code is not working because you use .push() on object, not on array.
Try this:
this.editObj.forEach(item => item["key"] = this.checked);

In everything except IE11
Creating a new array
const array = [{
name: 'name',
},
{
name: 'name',
},
{
name: 'name',
},
{
name: 'name',
},
];
console.log(array.map(x => ({
...x,
key: '123',
})));
Updating existing array
const array = [{
name: 'name',
},
{
name: 'name',
},
{
name: 'name',
},
{
name: 'name',
},
];
array.forEach((x) => {
x.key = '123';
});
console.log(array);
In IE11
var array = [{
name: 'name',
},
{
name: 'name',
},
{
name: 'name',
},
{
name: 'name',
},
];
for (var i = 0; i < array.length; i += 1) {
array[i].key = '123';
}
console.log(array);

Related

How to transform an array of objects to match objects in other arrays?

There is an array with the following data
Initial data
const data = [
{
type: 'first'
stats: [
{name: 'yes', value: 11},
{name: 'no', value: 33},
]
},
{
type: 'second',
stats: [
{name: 'call back', value: 32},
{name: 'no', value: 77},
]
},
{
type: 'third',
stats: [
{name: 'yes', value: 14},
]
}
]
I need help to convert data above to the next form
Expected result
const dataTransformed = [
{
type: 'first',
stats: [
{name: 'yes', value: 11},
{name: 'no', value: 33},
{name: 'call back', value: 0},//*zero because this object exist in third object but here doesnt
]
},
{
type: 'second',
stats: [
{name: 'yes', value: 0},//*zero because this object exist in first object but here doesnt
{namename: 'no', value: 77},
{name: 'call back', value: 32},
]
},
{
type: 'third',
stats: [
{name: 'yes', value: 14},
{name: 'no', value: 0},//*zero because this object exist in first object but here doesnt
{name: 'call back', value: 0},//*zero because this object exist in first object but here doesnt
]
}
]
That is, it is necessary that in each object in the stats array the order of objects with
the specified name corresponds to other objects, while if an object with the same name
there is no corresponding index, you need to create it with empty value.
const data=[{type:"first",stats:[{name:"yes",value:11},{name:"no",value:33}]},{type:"second",stats:[{name:"call back",value:32},{name:"no",value:77}]},{type:"third",stats:[{name:"yes",value:14}]}];
const names = [... new Set(data.reduce((a, x) => a.concat(x.stats.map(y => y.name)), []))];
const dataTransformed = data.map(x => ({
...x,
stats: names.map(name => ({
name,
value: (x.stats.find(z => z.name === name) || {value: 0}).value,
})),
}));
console.log(dataTransformed);
You can create an array of names, then check which names are presented in stats, using an default value when its not

JS split array of objects by object field

I have an array of tokens:
[
{type: 'name', value: 'foo'},
{type: 'string', value: 'bar'},
{type: 'special', value: ','},
{type: 'name', value: 'buzz'}
]
And I'd like to split them by value equal to ,:
[
[
{type: 'name', value: 'foo'},
{type: 'string', value: 'bar'}
],
[
{type: 'name', value: 'buzz'}
]
]
How should I do it?
You can use Array.reduce() to iterate the items. There are three cases:
The item's value is , - add a new sub-array without the item.
There is no sub-array - add a new sub-array with the item.
The rest - add the item to the last sub-array.
const data = [
{type: 'name', value: 'foo'},
{type: 'string', value: 'bar'},
{type: 'special', value: ','},
{type: 'name', value: 'buzz'}
];
const result = data.reduce((r, o) => {
if(o.value === ',') return [...r, []];
if(!r.length) return [[o]];
r[r.length - 1].push(o);
return r;
}, []);
console.log(result);
Using forEach
let arr = [
{type: 'name', value: 'foo'},
{type: 'string', value: 'bar'},
{type: 'special', value: ','},
{type: 'name', value: 'buzz'}
]
let op = [];
let temp = [];
arr.forEach((e,i)=>{
if(e.value === ',' && temp.length){
op.push(temp);
temp =[];
} else {
temp.push(e);
}
});
if(temp.length) op.push(temp);
console.log(op);

flatten javascript array of objects

I have an array of object with hierarchical structure, something like this:
[
{name: 'ParentOne', children: [
{name: 'ParentOneChildOne'},
{name: 'ParentOneChildTwo', children: [
{name: 'ParentOneChildTwoGrandChildOne'},
]},
]},
{name: 'ParentTwo', children: [
{name: 'ParentTwoChildOne', children: [
{name: 'ParentTwoChildOneGrandChildOne'},
{name: 'ParentTwoChildOneGrandChildTwo'}
]},
{name: 'ParentTwoChildTwo'}
]}
];
I want to flatten it:
[
{name: 'ParentOne'},
{name: 'ParentOneChildOne'},
{name: 'ParentOneChildTwo'},
{name: 'ParentOneChildTwoGrandChildOne'},
{name: 'ParentTwo'},
{name: 'ParentTwoChildOne'},
{name: 'ParentTwoChildOneGrandChildOne'},
{name: 'ParentTwoChildOneGrandChildTwo'},
{name: 'ParentTwoChildTwo'}
]
I have tried _.flatten() and _.flatMap(), but it does not produce what I need. What is the best way to achieve it preferably using lodash.js or underscore.js.
No need for underscore/lodash.
const arr = [
{name: 'ParentOne', children: [
{name: 'ParentOneChildOne'},
{name: 'ParentOneChildTwo', children: [
{name: 'ParentOneChildTwoGrandChildOne'},
]},
]},
{name: 'ParentTwo', children: [
{name: 'ParentTwoChildOne', children: [
{name: 'ParentTwoChildOneGrandChildOne'},
{name: 'ParentTwoChildOneGrandChildTwo'}
]},
{name: 'ParentTwoChildTwo'}
]}
];
function flatten(arr) {
return arr? arr.reduce((result, item) => [
...result,
{ name: item.name },
...flatten(item.children)
], []) : [];
}
console.log(flatten(arr));
Recursive functions is the way to go for any depth of iteration.
With some ES2015 and LoDash/Underscore
var arr = [{
name: 'ParentOne',
children: [{
name: 'ParentOneChildOne'
}, {
name: 'ParentOneChildTwo',
children: [{
name: 'ParentOneChildTwoGrandChildOne'
}, ]
}, ]
}, {
name: 'ParentTwo',
children: [{
name: 'ParentTwoChildOne',
children: [{
name: 'ParentTwoChildOneGrandChildOne'
}, {
name: 'ParentTwoChildOneGrandChildTwo'
}]
}, {
name: 'ParentTwoChildTwo'
}]
}];
var res = _.reduce(arr, (a, b) => {
(rec = item => {
_.each(item, (v, k) => (_.isObject(v) ? rec(v) : a.push(_.zipObject([k], [v]))))
})(b);
return a;
}, []);
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
I would use .reduce and recursion to do this. Here's my implementation using Array.reduce, but you could do much the same with underscore's reduce function.
const arr = [
{name: 'ParentOne', children: [
{name: 'ParentOneChildOne'},
{name: 'ParentOneChildTwo', children: [
{name: 'ParentOneChildTwoGrandChildOne'},
]},
]},
{name: 'ParentTwo', children: [
{name: 'ParentTwoChildOne', children: [
{name: 'ParentTwoChildOneGrandChildOne'},
{name: 'ParentTwoChildOneGrandChildTwo'}
]},
{name: 'ParentTwoChildTwo'}
]}
];
function flatten(arr) {
return arr.reduce((result, current) => {
if (current.children) {
const children = flatten(current.children);
delete current.children;
result.push(current);
result.push(...children);
} else {
result.push(current);
}
return result;
}, [])
}
console.log(flatten(arr));
You could try adapting the flatten function given in this answer, and slightly twist the logic to your object's structure.
//Your object
var data = [{
name: 'ParentOne',
children: [{
name: 'ParentOneChildOne'
},
{
name: 'ParentOneChildTwo',
children: [{
name: 'ParentOneChildTwoGrandChildOne'
}, ]
},
]
},
{
name: 'ParentTwo',
children: [{
name: 'ParentTwoChildOne',
children: [{
name: 'ParentTwoChildOneGrandChildOne'
},
{
name: 'ParentTwoChildOneGrandChildTwo'
}
]
},
{
name: 'ParentTwoChildTwo'
}
]
}
];
//georg's flatten function
flatten = function(x, result, prefix) {
if (_.isObject(x)) {
_.each(x, function(v, k) {
flatten(v, result, prefix ? prefix + '_' + k : k)
})
} else {
result[prefix] = x
}
return result
}
//using the function on your data
result = flatten(data, {});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
Does this help at all?
You could use some destruction and use a recursive function for collecting all wanted items.
var array = [{ name: 'ParentOne', children: [{ name: 'ParentOneChildOne' }, { name: 'ParentOneChildTwo', children: [{ name: 'ParentOneChildTwoGrandChildOne' },] },] }, { name: 'ParentTwo', children: [{ name: 'ParentTwoChildOne', children: [{ name: 'ParentTwoChildOneGrandChildOne' }, { name: 'ParentTwoChildOneGrandChildTwo' }] }, { name: 'ParentTwoChildTwo' }] }],
flat = (r, { name, children = [] }) => [...r, { name }, ...children.reduce(flat, []) ],
result = array.reduce(flat, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
On EDGE, you need a different use of default values.
var array = [{ name: 'ParentOne', children: [{ name: 'ParentOneChildOne' }, { name: 'ParentOneChildTwo', children: [{ name: 'ParentOneChildTwoGrandChildOne' },] },] }, { name: 'ParentTwo', children: [{ name: 'ParentTwoChildOne', children: [{ name: 'ParentTwoChildOneGrandChildOne' }, { name: 'ParentTwoChildOneGrandChildTwo' }] }, { name: 'ParentTwoChildTwo' }] }],
flat = (r, { name, children }) => [...r, { name }, ...(children || []).reduce(flat, []) ],
result = array.reduce(flat, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to chain this reduce and map function

Both of these parameters are a list of objects. They both contain the property Name. I would like to project a few of their properties where the property Name are equal. The following gives the correct result. However, can someone help me refactor it to one traversal?
export function fieldProjections(docTypeFields, recordFields) {
const recordsByName = recordFields.reduce(function (rec, field) {
rec[field.Name] = field;
return rec;
}, {});
const fields = docTypeFields.map(dt => {
return {
'Name': dt.Name,
'RawValue': recordsByName[dt.Name].RawValue,
'Type': dt.DataType,
'Value': recordsByName[dt.Name].Value,
'Id': dt.DocumentTypeFieldID
};
});
return fields;
}
let docTypeFields = [{Name: 'doc1', RawValue: '8', Type: 'large', Value: '3.50', Id: '1'},{Name: 'doc2', RawValue: '11', Type: 'medium', Value: '4.50', Id: '2'},{Name: 'doc3', RawValue: '81', Type: 'largish', Value: '3.60', Id: '3'},{Name: 'doc4', RawValue: '22', Type: 'small', Value: '2.50', Id: '4'}],
recordFields = [{Name: 'doc1', Field: 'field1'},{Name: 'doc2', Field: 'field2'},{Name: 'doc3', Field: 'field3'},{Name: 'doc4', Field: 'field4'}];
docTypeFields.forEach(doc => {
let siblingRecord = recordFields.find(record => record.Name === doc.Name);
if (siblingRecord) doc.Field = siblingRecord.Field;
});
console.log(docTypeFields);

Javascript: Finding index of an object in an array, based on a value within a nested array on the objects

I have an array that looks like this:
[{
name: 'foobar',
fields: [{
label: 'argle'
},{
label: 'bargle'
}]
},{
name: 'baz',
fields: [{
label: 'rar'
},{
label: 'hoogah'
}]
}]
I'm looking for the index of the object which has a field matching label === 'rar', so I can update that particular field. Is there an optimum way to accomplish this? I know indexOf won't get me there by itself, but I'm struggling with the logic.
You can use the findIndex and some methods of Array.
[
{name: 'foobar', fields: [{label: 'argle'}, {label: 'bargle'}]},
{name: 'baz', fields: [{label: 'rar'}, {label: 'hoogah'}]}
].findIndex(function(element, index, array) {
return element.fields.some(function(element, index, array) {
return element.label === 'rar';
});
})
returns 1
With arrow functions you can do the searches shown in Mathieu's answer nice and cleanly
let arr = [
{name: 'foobar', fields: [{label: 'argle'}, {label: 'bargle'}]},
{name: 'baz', fields: [{label: 'rar'}, {label: 'hoogah'}]}
];
Then
arr.findIndex(item => item.fields.some(deepItem => deepItem.label === 'rar')); // 1
If you're more interested in accessing the item itself, not it's index, then use arr.find instead
arr.find(item => item.fields.some(deepItem => deepItem.label === 'rar')); // Object
Further, if you want every item which matches, then use arr.fileter instead
arr.filter(item => item.fields.some(deepItem => deepItem.label === 'rar')); // [{...}, ...]
a 'normal' way of doing it:
var arr = [
{name: 'foobar', fields: [{label: 'argle'}, {label: 'bargle'}]},
{name: 'baz', fields: [{label: 'rar'}, {label: 'hoogah'}]},
{name: 'foo', fields: [{label: 'asjda'}, {label: 'hoogah'}]}
];
function findByLabel(arr, str) {
var res = null;
arr.forEach(function(item) {
if (item.fields[0].label == 'rar')
res = item
});
return res;
}
console.log(findByLabel(arr, 'rar'));
Demo: https://jsfiddle.net/5h8ugasf/4/
an ugly way of doing it.
var data = [
{name: 'foobar', fields: [{label: 'argle'}, {label: 'bargle'}]},
{name: 'baz', fields: [{label: 'rar'}, {label: 'hoogah'}]}
],
i = data.findIndex(e => ~e.fields.findIndex(f => f.label == 'rar'));
// returns 1

Categories