Assemble the data through JS Map - javascript

code1:
let commap = new Map();
data.forEach(function(item,index){
if(commap.has(item.comp)){
let arr = companyset.get(item.comp);
arr.push(item);
commap.set(item.comp,arr);
}else{
commap.set(item.comp,[item]);
}
});
code2:
let commap = new Map();
data.forEach(function(item,index){
commap .set(item.comp,commap.has(item.comp)?commap.get(item.comp).push(item):[item]);
});
The logic of the two pieces of code is the same, if there is more than one entry for company,code2 throw an error:'Uncaught TypeError: commap.get(...).push is not a function',
why did this error occur,is it the order of js execution?
Thanks a lot

The problem is that .push returns the new length of the array, not the array itself. So, when you set the value to companyset.get(item.company).push(item), you're setting the value to a number, not an array, which means when you try to push to it later, an error is thrown.
Remember that arrays, being non-primitive, can be changed simply with a reference to the array, without having to re-assign it. You only have to set the first time you come across a new company. Try something like this instead:
const data = [
{ company: 'foo' },
{ company: 'bar' },
{ company: 'foo' },
{ company: 'foo' },
];
const companyset = new Map();
data.forEach(function(item) {
const { company } = item;
const arr = companyset.get(company);
if (!arr) return companyset.set(company, [item]);
arr.push(item);
});
console.log(companyset.get('foo'));
But to combine an array into an object, it would be more appropriate to use reduce instead of forEach:
const data = [
{ company: 'foo' },
{ company: 'bar' },
{ company: 'foo' },
{ company: 'foo' },
];
const companyset = data.reduce((map, item) => {
const { company } = item;
const arr = map.get(company);
if (!arr) map.set(company, [item]);
else arr.push(item);
return map;
}, new Map());
console.log(companyset.get('foo'))

Related

Merging values from an array of strings into a nested object in javascript

I want to merge values from an array into a static nested object. The array containing the values is something like this,
['name=ABC XYZ', 'hobbies=[M,N,O,P]', 'profession=S', 'age=27']
and the object in which the values has to be merged is,
const person = {
details_1: {
name: null,
hobbies: null,
profession: null
},
details_2: {
age: null
}
};
I want my output object to look like below,
const updated_person = {
details_1: {
name: 'ABC XYZ',
hobbies: [M,N,O,P],
profession: 'S'
},
details_2: {
age: 27
}
};
Thanks a lot for your help!
I made another solution with a different approach.
Here I used an interface weher I described the desired data structure.
In the second part the string array is tranformed into key and value pairs. Thereform are filtered the keys of interface and added into an empty object literal.
const data = ["name=ABC XYZ", "hobbies=[M,N,O,P]", "profession=S", "age=27"];
const dataInterface = {
details_1: { name: null, hobbies: null, profession: null },
details_2: { age: null },
};
function orederData(arr) {
const record = arr.map((item) => {
let [key, value] = item.split("=");
if (value[0] === "[" && value[value.length - 1] === "]") {
value = value.slice(1, value.length - 1).split(",");
}
return { key, value };
});
const dataBlock = {};
Object.keys(dataInterface).map((detail) => {
dataBlock[detail] = {};
Object.keys(dataInterface[detail]).forEach((dataKey) => {
dataBlock[detail][dataKey] = record.filter((record) => {
return record.key === dataKey;
})[0].value;
});
});
return dataBlock;
}
const orderedData = orederData(data);
console.log(orderedData);
You can simply achieve this by iterating the input array.
const arr = ['name=ABC XYZ', 'hobbies=[M,N,O,P]', 'profession=S', 'age=27'];
const person = {
details_1: {},
details_2: {}
};
arr.forEach(item => {
(item.split('=')[0] !== 'age') ? person.details_1[item.split('=')[0]] = item.split('=')[1] : person.details_2[item.split('=')[0]] = item.split('=')[1]
});
console.log(person);
There is no way to cleanly merge an unstructured array into a structured object such that the array values end up in the appropriately keyed person properties.
javascript does provide the assign() function that merges objects but for YOUR requirements your source data needs to be an object similarly structured and not an array.
so this:
['name=ABC XYZ', 'hobbies=[M,N,O,P]', 'profession=S', 'age=27']
would need to become this:
const source= [{details_1: {"name":"ABC XYZ", "hobbies":"[M,N,O,P]", "profession":"S"}, details_2: {"age":"27"}}]
such that a call to Object.assign():
const new_person = Object.assign(person, source[0]);
fills this
const person = {
details_1: {
name: null,
hobbies: null,
profession: null
},
details_2: {
age: null
}
};
properly, though you may need to clone or instantiate and empty person first.
or, if person is an Object you could have a fill() method that knows what to do with the array data.

how to get array according to conditions in javascript

My array comes like this
var data=[{PRODUCT : P1}, {PRODUCT: P2}]
I wantt to convert this into [P1, P2].
Sometimes my array comes like this
var data=[{ITEM: I1, QUANTITY:1}, {ITEM: I2, QUANTITY:2}]
I wantt to convert this into [I1, I2].
so can we make a common function, where I just want to extract particular value of array and make a new array.
p.s. Thank you in advance
I tried to write the logic like this:
data.map((d, index) => { var result= [];
result.includes(d[0]); })
but it,s not dynamic
You could define a function which will always get the first value of the first object key, this should satisfy your needs based on the above
var data1 = [{
ITEM: 'I1',
QUANTITY: 1
}, {
ITEM: 'I2',
QUANTITY: 2
}]
var data2 = [{
PRODUCT: 'P1'
}, {
PRODUCT: ' P2'
}]
function getArrayOfValues(list) {
return list.reduce((acc, x) => {
const firstValue = Object.values(x)[0];
acc.push(firstValue)
return acc;
}, [])
}
const result1 = getArrayOfValues(data1)
console.log(result1)
const result2 = getArrayOfValues(data2)
console.log(result2)
function getProductOrItem(list) {
return list.reduce((accumulator, obj) => {
if (obj.PRODUCT) {
accumulator.push(obj.PRODUCT);
} else if (obj.ITEM) {
accumulator.push(obj.ITEM);
}
return accumulator;
}, [])
}
you can iterate through your array with map() method and inside it extract the value of a first entity of an object in your array and simply get a new array with all values:
const data1 =[{PRODUCT : 'P1'}, {PRODUCT: 'P2'}]
const data2 = [{ITEM: 'I1', QUANTITY: 1}, {ITEM: 'I2', QUANTITY: 2 }]
const transformValuesOfArray = (arrayToTransform) =>
arrayToTransform.map(value => {
const firstObjectValue = Object.values(value)[0]
return firstObjectValue
})
console.log(transformValuesOfArray(data1))
console.log(transformValuesOfArray(data2))

How to set the defaults of an array that has an unknown number of objects?

I know how to set the defaults of an object:
store.currentUser = {
username: ''
}
And set new values to it:
store.getCurrentUser = () => {
const currentUser = Parse.User.current()
store.currentUser.username = currentUser.username
}
}
But I can't do that if I have an array:
store.buildings = [
// how to set the defaults here?
]
Because the number of objects that the array can contain is unknown:
store.findBuildings = () => {
const query = new Parse.Query(Building)
return query.find({
success: (buildings) => {
// _.map(buildings, (building) => building.toJSON())
// -> [ {name: 'Name 1'}, {name: 'Name 2'}, etc... ]
// how to give the new values to store.buildings?
},
error: (buildings, error) => {
console.log('Error:', error.message)
}
})
}
Is here any way to accomplish this?
Note: I can't just do buildings = [] because I need the keys to have defaults in order for the reactivity of my app to work.
Check this answer
Array.prototype.repeat= function(what, L){
while(L) this[--L]= what;
return this;
}
var A= [].repeat(0, 24);
Or using second answer
var a = Array.apply(null, Array(24)).map(function() { return /your object here/ });
// or:
var a = Array.apply(null, Array(5)).map(Boolean).map(Number);

Turn object into array, add object as new element

Trying to transform an object of objects:
var items: {
item_a: {
state: 'item_a status'
},
item_b: {
state: 'item_b status'
}
};
into an array of objects, whilst adding a new array element to the object (the object key):
var items = [{
name: 'item_a',
state: 'item_a status'
}, {
name: 'item_b',
state: 'item_b status'
}];
My naive attempt, which works, is thus:
var arrayOfItems = [];
for(var x in items){
var itemObj = {
name: x
};
for(var y in items[x]){
itemObj[y] = items[x][y];
}
arrayOfItems.push(itemObj);
}
I'm wondering if there's a cleaner way to do this, using maybe something Underscore/LoDash?
I would use map() for this:
_.map(items, function(item, key) {
return _.assign({ name: key }, item);
});
// →
// [
// {
// name: 'item_a',
// state: 'item_a status'
// },
// {
// name: 'item_b',
// state: 'item_b status'
// }
// ]
Since map() always returns an array, you're halfway there. You just need the callback to generate your array items. You can use the assign() function to setup your new name property, and then add the rest of the properties.
var newItems = _.map(items, function(item, key){
item.name = key;
return item;
});
console.log(newItems);

Reordering array objects via javascript

I have been doing some sorting and still dont get it why the result is []. could you guys help me out what im missing?
I have my raw array object:
var data = [
{message:'hello', username:'user1'},
{message:'data', username:'user1'},
{message:'sample', username:'user2'},
{message:'here', username:'user2'},
];
my function is:
var chat = [];
function reorder(obj) {
obj.forEach( function(val, i) {
if(typeof chat[val.username] === 'undefined') {
chat[val.username] = [];
chat[val.username].push(val);
}
else
chat[val.username].push(val);
});
return chat;
}
and on my console:
reorder(data);
I am expecting to have:
var data2 = [
'user1': [{message:'hello', username:'user1'}, {message:'data', username:'user1'} ],
'user2': [{message:'sample', username:'user2'}, {message:'here', username:'user2'} ],
];
You can do this easily with reduce:
var data2 = data.reduce(function(acc, x) {
acc[x.username] = (acc[x.username] || []).concat(x)
return acc
},{})
/*^
{ user1:
[ { message: 'hello', username: 'user1' },
{ message: 'data', username: 'user1' } ],
user2:
[ { message: 'sample', username: 'user2' },
{ message: 'here', username: 'user2' } ] }
*/
The problem is that you made chat an array. When you look at an array in the console, it only displays the numeric indexes, not the named properties; you have to use console.log(chat) to see the named properties.
Since you want this to be an object with named properties, you should declare it as an object, not an array:
var chat = {};
Use Underscore's _.groupBy:
_.groupBy(data, 'username')

Categories

Resources