JS split array of objects by object field - javascript

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);

Related

How to return an array after adding and then sorting it in Javascript?

I have below piece of code,
What I am trying to do is add a new record at the 0th position and then sort the array based on the label. But I can't get it to work; I am getting an empty array.
const array = [{id: '3', name: 'name1'},
{id: '4', name: 'name2'},
{id: '5', name: 'name3'}]
const items = array
.map((sp) => ({ label: sp.name, value: sp.id }))
.splice(0, 0, { label: '', value: '' })
.sort((a, b) => a.label - b.label);
console.log(items);
Is this what you want?
const array = [
{ id: '3', name: 'name1' },
{ id: '4', name: 'name2' },
{ id: '5', name: 'name3' }
]
const items = array.map((sp) => ({ label: sp.name, value: sp.id }))
items.unshift({ label: '', value: ''})
items.sort((a, b) => a.value - b.value);
console.log(items);
Output:
[
{ label: '', value: '' },
{ label: 'name1', value: '3' },
{ label: 'name2', value: '4' },
{ label: 'name3', value: '5' }
]
Method unshift here is used to add a new value at the beginning of the list. Both sort and unshift works in place therefore they do not return the modified array and update the existing variable instead.
The error in this code is that the .splice() method returns an array containing the removed items, and does not modify the original array. So, the original array is not modified when .splice() is called on it. To fix this, you can assign the return value of .splice() to the original array:
const array = [{id: '3', name: 'name1'},
{id: '4', name: 'name2'},
{id: '5', name: 'name3'}]
const items = array
.map((sp) => ({ label: sp.name, value: sp.id }))
.splice(0, 0, { label: '', value: '' })
.sort((a, b) => a.label - b.label);
array = items;
console.log(array);

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

Angular 2 add key and value to each array object

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);

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