Convert key/value array - javascript

What is the best way to convert to following array. Do I need to map over it or is there some other way with Object.values etc:
[
{
key: "eyeColor",
value: "Blue/Green",
},
{
key: "eyeColor",
value: "Blue",
},
{
key: "hairColor",
value: "black",
}
];
into:
{
hairColor: ["Blond", "Brown"],
eyeColor: ["Blue"],
}

Using Array#reduce, iterate over the array while updating a Map where the key is the key properties and the value is the corresponding grouped-value properties.
Using Array#map, iterate over the above pairs and convert to objects:
const data = [ { key: "eyeColor", value: "Blue/Green" }, { key: "eyeColor", value: "Blue" }, { key: "hairColor", value: "black" } ];
const groupedPairs = [...data.reduce((map, { key, value }) => map.set(key, [...(map.get(key) ?? []), value]), new Map)];
const list = groupedPairs.map(([ prop, list ]) => ({ [prop]: list }))
console.log(list);
EDIT AFTER CHANGE OF EXPECTED OUTPUT:
const data = [ { key: "eyeColor", value: "Blue/Green" }, { key: "eyeColor", value: "Blue" }, { key: "hairColor", value: "black" } ];
const res = data.reduce((acc, { key, value }) => ({
...acc, [key]: [...(acc[key] ?? []), value]
}), {});
console.log(res);

Related

How to change the current array format to just an array of objects format?

How can I change the following data structure that is coming from the api into the desired format that is defined below?
inspectionViewAllRs = [
{
INSPN_XFER_SEQ_NR: {
value: '5'
},
FNRL_FLG: {
label: 'No',
value: 'N'
},
HAS_PAST_INSPN: {
value: '3'
},
MTG_CO_PHN_AREA_CD: {
value: ''
},
DECLARATION_CD: {
label: 'US Citizen/Non-Citizen National',
value: 'CZ'
},
....
....
....
},
{ ... }
{ ... }
{ ... }
]
How can I just convert it into this an array of objects format?
inspectionViewAllRs = [
{ label: "", value: '5' },
{ label: "No", value: "N" },
{ label: "", value: "3" },
{ label: "", value: "" },
{ label: "US Citizen/Non-Citizen National", value: "CZ" },
....
....
....
]
I tried to do the following but this doesn't help much:
if(!_.isEmpty(this.state.inspectionViewAllRsData)) {
const result = this.state.inspectionViewAllRsData.map((data, i) => {
const items = Object.values(data);
const newItem = {}
newItem.label = items[i].label;
newItem.value = items[i].value;
return newItem
})
console.log("result ", result)
// this is what I see printed out in console log
// result (5) [{…}, {…}, {…}, {…}, {…}]
0: {label: undefined, value: "5"}
1: {label: "No", value: "N"}
2: {label: undefined, value: "3"}
3: {label: undefined, value: ""}
4: {label: "", value: ""}
length: 5
}
Why am I not getting return all the rest of the data?
Using Array#flatMap and Object#values to get one list of the objects values, and then Array#map to get the same attributes in all:
const inspectionViewAllRs = [
{
INSPN_XFER_SEQ_NR: { value: '5' },
FNRL_FLG: { label: 'No', value: 'N' },
HAS_PAST_INSPN: { value: '3' },
MTG_CO_PHN_AREA_CD: { value: '' },
DECLARATION_CD: { label: 'US Citizen/Non-Citizen National', value: 'CZ' },
},
{
DECLARATION_CD: { label: 'US Citizen/Non-Citizen National', value: 'CZ' },
}
];
const res = inspectionViewAllRs
.flatMap(Object.values) // get one list of objects
.map(({ label = '', value = '' }) => ({ label, value })); // return list of label/value objects
console.log(res);
You will need to use .flatMap and map on the items .values.
You API repsonse looks like:
[
{ unneeded_keys: Needed_Values}, //objectOfData
{ unneeded_keys: Needed_Values},
{ unneeded_keys: Needed_Values},
]
Your state.inspectionViewAllRsData array contains these objects. The actual data you need is inside Needed_Values.
So, you need to do:
// Note: flatMap here \/\/\/
const result = this.state.inspectionViewAllRsData.flatMap((objectOfData) => {
const items = Object.values(data);
return items.map((item, i) => {
return {
label: item.label ?? '', // handle case when label is undefined
value: item.value,
}
}
})
The reason you need to use flatMap is because each obj in your API response, will return multiple elements as per your transformed data. So, flatMap will automatically flatten the array of array of objects to array of objects.

How to convert array of objects into enum like key value pair in javascript?

I have an array
const a = [
{ name: "read-web-courses" },
{ name: "example" },
{ name: "t_gql" },
{ name: "ddddd" },
];
I am trying it to reduce it to the below given output , However I am stuck
Output
{0:"read-web-courses",1:"example",2:"t_gql",3:"ddddd"}
You could map the wanted property and assign the pairs to the object.
const
array = [{ name: "read-web-courses" }, { name: "example" }, { name: "t_gql" }, { name: "ddddd" }],
result = Object.assign({}, array.map(({ name }) => name));
console.log(result);
You can use Array.reduce like below.
const a = [
{ name: "read-web-courses" },
{ name: "example" },
{ name: "t_gql" },
{ name: "ddddd" },
];
const convert = arr => (
arr.reduce((total, value, index) => {
total[index] = value.name;
return total;
}, {})
)
console.log(convert(a));
This is accomplished using Array#reduce, where you can use the index from the reduce callback as the key of the new object:
const a = [ { name: "read-web-courses" }, { name: "example" }, { name: "t_gql" }, { name: "ddddd" }];
const res = a.reduce((r, o, i) => {
r[i] = o.name;
return r;
}, {});
console.log(res);
Also one more approach using Object#fromEntries and Array#map, where each object is converted to an array of key, value pairs:
const a = [ { name: "read-web-courses" }, { name: "example" }, { name: "t_gql" }, { name: "ddddd" }];
const res = Object.fromEntries(a.map((o, i) => [i, o.name]));
console.log(res)

Transforming array of objects based upon key - javascript

I am trying to figure out the most efficient method for reducing an array of objects based upon a unique key (key/values are dynamically returned in this case). I've tried to a combination of different methods using concat, map, or filter but haven't had much luck.
Original array of objects:
[
{
key: "Name",
value: "John"
},
{
key: "Company",
value: "Acme"
},
{
key: "Name",
value: "Jack"
},
{
key: "Name",
value: "Matt"
},
{
key: "Last",
value: "Test"
}
]
Desired Array:
[
{
key: "Name",
values: [
"John",
"Jack",
"Matt"
]
},
{
key: "Company",
values: [
"Acme"
]
},
{
key: "Last",
values: [
"Test"
]
}
]
Prob other ways, but a simple for loop would suffice:
const data = [{
key: "Name",
value: "John"
},
{
key: "Company",
value: "Acme"
},
{
key: "Name",
value: "Jack"
},
{
key: "Name",
value: "Matt"
},
{
key: "Last",
value: "Test"
}
]
let result = {}
for (const i in data) {
result[data[i].key] = {
key: data[i].key,
values: [
...result[data[i].key] ? result[data[i].key].values : [],
data[i].value
]
}
}
console.log(Object.values(result))
You can use reduce to build a new object using name as the keys, and then use Object.values to create the output you need from the object:
const data = [
{ key: "Name", value: "John" },
{ key: "Company", value: "Acme" },
{ key: "Name", value: "Jack" },
{ key: "Name", value: "Matt" },
{ key: "Last", value: "Test" }
];
const out = Object.values(data.reduce((acc, { key, value }) => {
// If the key doesn't exist on the object, add it
// and initialise the value object
acc[key] = acc[key] || { key, values: [] };
// Push the value from the current iteration
// into the values array
acc[key].values.push(value);
// Return the accumulator for the next iteration
return acc;
}, {}));
console.log(out);
I think reduce is the best solution here :)
const initialArray = [
{
key: "Name",
value: "John"
},
{
key: "Company",
value: "Acme"
},
{
key: "Name",
value: "Jack"
},
{
key: "Name",
value: "Matt"
},
{
key: "Last",
value: "Test"
}
];
const result = initialArray.reduce((acc, obj) => {
/* try to find object in the result array
returns index or -1 if object is missing
*/
const existingIndex = acc.findIndex(item => item.key === obj.key);
if (existingIndex > -1) {
/* object already exists, update its values array */
acc[existingIndex].values.push(obj.value);
return acc;
} else {
/* the key is first encountered, create an object in the result array */
acc.push({
key: obj.key,
values: [obj.value],
});
return acc;
}
}, []); // [] - default value is an empty array
console.log(result);

Filter the array with some criteria ES6

Hello guys I would like some code in ES6 javascript that solves this problem my data is an array of objects like the following
array = [
{
name: "SI",
value: 3
},
{
name: "MI",
value: 2
},
{
name: "SI",
value: 7
},
{
name: "SI",
value: 9
},
{
name: "MI",
value: 3
}
]
Just I want to take distinct object based on name with highest value like the following result
result = [
{
name: "SI",
value: 9
},
{
name: "MI",
value: 3
}
]
You can use array#reduce to accumulate the distinct name in an object accumulator. For each stored object, compare the value with the stored value and update in case it is less than the current value
let arr = [ { name:"SI", value:3 }, { name:"MI", value:2 }, { name:"SI", value:7 }, { name:"SI", value:9 }, { name:"MI", value:3 } ],
result = Object.values(arr.reduce((r,{name, value}) => {
r[name] = r[name] || {name, value: 0};
if(r[name].value < value)
r[name].value = value;
return r;
},{}));
console.log(result);
.as-console-wrapper {max-height: 100% !important; top: 0;}
Probably most efficient by reducing to an intermediate object first, and then mapping that object's entries:
const result = Object.entries(array.reduce((a, {name, value}) => {
a[name] = a[name] && a[name] >= value ? a[name] : value;
return a;
}, {})).map(([name, value]) => ({name, value}));
Complete snippet:
const array = [{
name: "SI",
value: 3
},
{
name: "MI",
value: 2
},
{
name: "SI",
value: 7
},
{
name: "SI",
value: 9
},
{
name: "MI",
value: 3
}
];
const result = Object.entries(array.reduce((a, {name, value}) => {
a[name] = a[name] && a[name] >= value ? a[name] : value;
return a;
}, {})).map(([name, value]) => ({name, value}));
console.log(result);

How to merge Array of Objects based on the same value?

I have this array of Objects:
var array = [{
country: "Austria",
name: "2019-01-04T23:00:00.000Z",
value: "1"
},
{
country: "Austria",
name: "2019-01-11T23:00:00.000Z",
value: "3"
},
{
country: "Austria",
name: "2019-01-18T23:00:00.000Z",
value: "1"
}
]
I want manipulate this to achieve this result:
var array = [{
country: "Austria",
series: [{
name: "2019-01-04T23:00:00.000Z",
value: "1"
},
{
name: "2019-01-11T23:00:00.000Z",
value: "3"
},
{
name: "2019-01-18T23:00:00.000Z",
value: "1"
}
]
}]
I read many questions but none helped me.
You could loop thorugh the array. Use destructuring to get country and rest of the properties separately. Add each unique country to group object as key and push the rest object to the series array. Then use Object.values() to get the values as an array
const array=[{country:"Austria",name:"2019-01-04T23:00:00.000Z",value:"1"},{country:"Austria",name:"2019-01-11T23:00:00.000Z",value:"3"},{country:"Austria",name:"2019-01-18T23:00:00.000Z",value:"1"}];
const group = {};
array.forEach(({ country, ...rest }) => {
group[country] = group[country] || { country, series: [] };
group[country].series.push(rest)
})
console.log(Object.values(group))
This should do:
var map = {};
for(var entity of array) {
if(!map[entity.country]) {
map[entity.country] = {
country: entity.country,
series: [
{
name: entity.name,
value: entity.value
}
]
};
}
else {
map[entity.country].series.push({
name: entity.name,
value: entity.value
});
}
}
var mappedArray = Object.values(map);
Here is functional solution without for loops and mutable variables:
const result = array.reduce((carry, item) => {
if (!carry.includes(item.country)) {
carry.push(item.country);
}
return carry;
}, []).map(country => {
return {
country: country,
series: array.filter(item => item.country === country).map(item => {
return {
name: item.name,
value: item.value
};
})
};
You can do something like:
const result = array
.map(
c => ({
country: c.country,
series: array
.filter(d => d.country === c.country)
.map(
d => ({
name: d.name,
value: d.value
})
)
})
)

Categories

Resources