Creating a key:value object from a flat object - javascript

I'm using Javascript to get data from an API.
I get the following list of objects.
[
{name: 'Cat', value: 2, extra: 'data'},
{name: 'Dog', value: 3, extra: 'data'}
]
I'm trying to get to the following form
[
cat: {value: 2},
dog: {value: 3}
]
I'm currently trying using map but I don't see where the key part comes in.
return data.map((item) => ({
value: item.value
}));

var data = [
{name: 'Cat', value1: 2, value2: 3},
{name: 'Dog', value1: 3, value2: 4}
]
var result = data.map((item) => {
var name = item.name
delete item.name
//if you want to modify some property
item.value1 = item.value1 + "$"
return {[name]: {...item}}
})
console.log(result)

const result = {};
for(const {name, value} of array)
result[name] = { value };
A plain old for loop does it. With functional programming you would have to use reduce to boil it down to one single object, map always returns an array.
const result = array.reduce((res, {name, value}) => ({ ...res, [name]: {value}}), {});

You can use Object.assign() with map() method to return object as a result.
const data = [{name: 'Cat', value: 2},{name: 'Dog', value: 3}]
const result = Object.assign({}, ...data.map(({name, value}) => ({[name]: {value}})))
console.log(result)

Related

Compare one array with a nested array and push value into a new array with same index in Javascript

I have 2 arrays
const arrayOne = [
{id: '110'},
{id: '202'},
{id: '259'}
];
const arrayTwo = [
{data: [{value: 'Alpha', id: '001'}]},
{data: [{value: 'Bravo', id: '202'}]},
{data: [{value: 'Charlie', id: '110'}]},
{data: [{value: 'Delta', id: '202'}]}
];
I need to create a new array comparing arrayOne[idx].id with arrayTwo[idx].data[idx2].id
Upon match, I need to create an array pushing value (arrayTwo[idx].data[idx2].value) to the new array against each index in arrayOne.
In this example, I would get newArray = [null, 'Bravo', null, Delta]
What I have tried:
arrayOne.map(item => ({
...item,
result: arrayTwo.filter(itemTwo => item.data.map(x => x.id).includes(itemTwo.id))
}));
and also
const newArr = [];
arrayOne.map((item, idx) => {
if (arrayTwo.filter(itemTwo => itemTwo.data?.map(x => x.id) === item.id)) {
newArr.push(arrayTwo.data[idx].value);
} else newArr.push(null);
});
To do this you can map arrayTwo and use .find() to search for the ID in arrayOne. I also mapped arrayTwo to the inner object to make the second map more concise.
const arrayOne = [
{id: '110'},
{id: '202'},
{id: '259'}
];
const arrayTwo = [
{data: [{value: 'Alpha',id: '001'}]},
{data: [{value: 'Bravo',id: '202'}]},
{data: [{value: 'Charlie',id: '777'}]},
{data: [{value: 'Delta',id: '202'}]}
];
const result = arrayTwo
.map(obj => obj.data[0])
.map(obj => (arrayOne.find(v => v.id === obj.id) && obj.value) || null)
console.log(result)
Use map to iterate over each element of arr1 and return a new array.
Reassemble the data attribute array of each element in the arr2 array
using map and flat
When arr1 traverses, you can get the current element id, use filter
to filter the combined data array, and return an element array that matches
the current element id.
Based on the case where the id is not matched, use the optional chain operator to get the value.
When returning
if you want to get the element array of the id and
value attributes, use conditional (ternary) operator, when it doesn't match, return the original element,
when it matches, use spread syntax, copy the current element
attribute, and add the value attribute
if you only want to get an
array of matching results, just return the value,
remember to use the optional chain operator to convert the unmatched
value to null.
const arr1 = [
{ id: '110' },
{ id: '202' },
{ id: '259' }
];
const arr2 = [
{ data: [{ value: 'Alpha', id: '001' }] },
{ data: [{ value: 'Bravo', id: '202' }] }
];
const result1 = arr1.map(o1 => {
const data = arr2.map(o2 => o2.data).flat();
const value = data.filter(o2 => o2.id === o1.id)[0]?.value;
return value ? {...o1, value} : o1;
});
const result2 = arr1.map(o1 => {
const data = arr2.map(o2 => o2.data).flat();
const value = data.filter(o2 => o2.id === o1.id)[0]?.value;
return value ?? null;
});
[result1, result2].forEach(r => console.log(JSON.stringify(r)));
You can try this easy line of code :
const arrayOne = [{ id: '110' }, { id: '202' }, { id: '259' }];
const arrayTwo = [{ data: [{ value: 'Alpha', id: '001' }], }, { data: [{ value: 'Bravo', id: '202' }] }];
let result = arrayOne.map(el => {
let found = arrayTwo.find(f => f.data.at(0)?.id == el.id)?.data.at(0)?.value;
return { id: el.id, value: found ?? null};
});
console.log(result);

Check equality of an objects array property and a nested object property

On my app I'm checking the equality between an objects array property and a nested object property - based on the results I return a new objects array.
The items objects array:
[{name: 'test345', value: 1, category: 'a'},{name: 'test2high', value: 2, category: 'b'},{name: 'test3low', value: 3, category: 'c'}]
The itemCategories object:
{testnum1: {name: 'test123', category: 'a', partialName: '345'}, testnum2: {name: 'test234', category: 'b', partialName: 'hight'}
I need to check the equality between the category properties and return the following objects array:
[{name: 'test', itemCategory: 'testnum1'},{name: 'test2', itemCategory: 'testnum2'}]
Below is what I did, it works fine, now I need to add a second check based on the item's name: I need to only return the items that their names include the partialName, any idea on how to adjust this?
export function getCategorizedItems(items) {
const categories = new Map(
Object.entries(itemCategories).map(([itemCategory, {category}]) => [
category,
itemCategory
])
)
return items
.map(item => ({
value: item.value,
category: categories.get(item.category)
}))
.filter(({category}) => category)
}
A basic approach be
create a comparison function
iterate over the items array
const items = [{name: 'test345', value: 1, category: 'a'},{name: 'test2high', value: 2, category: 'b'},{name: 'test3low', value: 3, category: 'c'}]
const itemCategories = {testnum1: {name: 'test123', category: 'a', partialName: '345'}, testnum2: {name: 'test234', category: 'b', partialName: 'hight'}}
const isEqual = (item, icItem) => {
return item.name.match(new RegExp(icItem.partialName + '$'))
&& item.category === icItem.category
}
const keyValues = Object.entries(itemCategories)
const res = items.flatMap(item => {
const itemCategory = keyValues.find(([, value]) => isEqual(item, value))
if (!itemCategory) return []
// return whatever you want based on item, key, value
return { item, itemCategory }
})
console.log('res', res)
If you prefer to use map (for the category lookup e.g) then you may store more data on the map (as value)
const items = [{name: 'test345', value: 1, category: 'a'},{name: 'test2high', value: 2, category: 'b'},{name: 'test3low', value: 3, category: 'c'}]
const itemCategories = {testnum1: {name: 'test123', category: 'a', partialName: '345'}, testnum2: {name: 'test234', category: 'b', partialName: 'hight'}}
const isEqual = (item, icItem) => {
return item.name.match(new RegExp(icItem.partialName + '$'))
&& item.category === icItem.category
}
const categoryToIc = new Map(Object.entries(itemCategories).map(([key, icItem]) => [icItem.category, { icItem, key }]))
const res = items.flatMap(item => {
const el = categoryToIc.get(item.category)
if (!el || !isEqual(item, el.icItem)) return []
// return whatever you want based on item, key, value
return { item, itemCategory: [el.key, el.icItem] }
})
console.log('res', res)

JavaScript Array push() method use to the id as the index value?

I want to use id as the index value and then generate a new array.
What better way do you have?
This is the result I want
Arr:Array[2]
3:"a"
8:"b"
Before processing
Arr:Array[2]
0:"a"
1:"b"
My code
var data = [{
id: 3,
name: 'a'
},
{
id: 8,
name: 'b',
}
]
var arr = []
const p = data.map(item => {
arr[item.id].push(item.name)
})
console.log(p)
You could use reduce, initialised with an empty array, set each index with id, and each value with name:
var data = [{
id: 3,
name: 'a'
},
{
id: 8,
name: 'b',
}
]
console.log(data.reduce((a, {id, name}) => (a[id] = name, a), []))
NOTE, you cannot have an array without indexes between values. Javascript will automatically fill these with undefined
If this doesn't fit your needs, then the only other option is to use an object (or a map but that's more complicated :P), which can still act like an array in a sense:
var data = [{
id: 3,
name: 'a'
},
{
id: 8,
name: 'b',
}
]
const obj = data.reduce((a, {id, name}) => (a[id] = name, a), {})
console.log(obj)
console.log(obj[3]) // a
console.log(obj[8]) // b

How to get a particular attribute from an array of array objects?

I have an Array of Arrays, and each Array consists of objects. Here is a simplified version of what I'm referring to (it is a console.log of my original array) -
Array - [Array(2), Array(3), Array(2)]
Each Array has objects in the following format (taking the first array from above) -
Array(2) -
0: {name: "test", score:40, date: "2018-09-18T00:00:00.000Z"}
1: {name: "test2", score:50 date: "2018-09-18T00:00:00.000Z"}
The other arrays are similar with the same attributes and different values.
I am trying to fetch the name attribute from each of these objects. I tried the below code - but I end up getting an undefined value:
const test1= array1.map(x=> x.values) // this gives me the array of arrays
const test2 = test1.map(function(y){return y.name})// this is my attempt to get the 'name' attribute from all of the arrays that include the objects.
What am I missing out on here? Is there a better way to get the attribute using arrow functions?
Flatten it, and map it to names or Vise versa
First flatten it, and map
const array = [[{name: 'test1'}, {name: 'test2'}], [{name: 'test3'}, {name: 'test4'}]]
var res = [].concat(...array).map(({name})=>name);
console.log(res);
Now, map it to names and then flatten
const array = [[{name: 'test1'}, {name: 'test2'}], [{name: 'test3'}, {name: 'test4'}]]
var res = [].concat(...array.map(a=>a.map(b=>b.name)))
console.log(res);
Now, In this one, certainly you can notice that we are actually mapping it in each level (we have to, no other way with first map only approach. so we can perform a reduce in place of the outer map and concat it there itself, so we can avoid the outer concat (for flatten) and inner concat will actually flatten it. Here we go:
const array = [[{name: 'test1'}, {name: 'test2'}], [{name: 'test3'}, {name: 'test4'}]]
var res = array.reduce((r, a)=>r.concat(a.map(b=>b.name)), []);
console.log(res);
/* TEST DATA */
array1 = [
{ name: 'test1', score: 40, date: '2018-09-18T00:00:00.000Z' },
];
array2 = [
{ name: 'test4', score: 50, date: '2018-09-18T00:00:00.000Z' },
{ name: 'test5', score: 40, date: '2018-09-18T00:00:00.000Z' },
];
array3 = [
{ name: 'test6', score: 50, date: '2018-09-18T00:00:00.000Z' },
{ name: 'test7', score: 50, date: '2018-09-18T00:00:00.000Z' },
{ name: 'test8', score: 40, date: '2018-09-18T00:00:00.000Z' },
{ name: 'test9', score: 50, date: '2018-09-18T00:00:00.000Z' },
];
testResults = [array1, array2, array3];
// Solution
function getListOfName(){
let names = [];
testResults.map(testResult => {
testResult.map(({name}) => {if(name) names.push(name)})
})
return names;
}
console.log("Full list of names", getListOfName());
// If you want to restrict to K names from each array
function getFirstKNamesfromArray(limit){
let names = [];
testResults.map(testResult => {
testResult.map(({name}, index) => {
if(name && (index < limit)) names.push(name)
})
})
return names
}
console.log("First 2 names from each array", getFirstKNamesfromArray(2));
Take into account that map returns an array; you iterate over it. Filter or reduce do the same.
const test1= array1.map(x=> x.values) // x doesn't have a property named "value"
//simply use forEach
array1.forEach((el) => console.log(el.name))
If you want to capture the names inside a collection:
const let container = [];
array1.forEach((el) => container.push(el.name))
A good way to better understand this iterator functions would be to first use loops and then attempt to "translate" your code into one of them.
Because in your first map x is an array, not an object. So, there is no value. You should map inner arrays then get the desired value.
const arr = [
[
{
name: "test",
score: 40,
date: "2018-09-18T00:00:00.000Z"
},
{ name: "test2", score: 50, date: "2018-09-18T00:00:00.000Z" }
],
[
{
name: "foo",
score: 40,
date: "2018-09-18T00:00:00.000Z"
},
{ name: "bar", score: 50, date: "2018-09-18T00:00:00.000Z" }
]
];
const test1 = arr
.map(x => x.map(y => y.name))
.reduce((acc, el) => [...acc, ...el], []);
console.log(test1);
This should work fine. You need to flatten the array structure and map the names.
const array = [[{name: 'test1'}, {name: 'test2'}], [{name: 'test3'}, {name: 'test4'}]]
const names = array.reduce((acc, innerArray) => {
return [...acc, ...innerArray.map(entry => entry.name)]
}, [])
console.log(names)
Here:
const arr = [
[{name: 'a', date:'x'}, {name: 'b', date:'y'}],
[{name: 'c', date:'x'}, {name: 'd', date:'y'}]
];
const names = arr.map(el => el.map(obj => obj.name));
console.log(names.join());
console.log(names.flat());
you can use flat() to keep names in an array or join() to merge the names into a string.
const test1= array1.map(x=> x.values)
This is returning undefined.
let requiredArr = [];
let array1 = [Array(2), Array(3), Array(2)]
let test2 = array1.map(x => x.map(y => requiredArr(y.name));
test2 will give the desired result.
Adding to Koushik's example, with ES2019, you can use flat() to flatten nested arrays:
const array = [[{name: 'test1'}, {name: 'test2'}], [{name: 'test3'}, {name: 'test4'}]]
var res = array.flat().map( ({name}) => name );
console.log(res);
Or if you have deeper levels:
const array = [[[{name: 'test1'}], {name: 'test2'}], [{name: 'test3'}, {name: 'test4'}]]
var res = array.flat(2).map( ({name}) => name );
console.log(res);
And so on.

Array to object with based on given key

I have an array declared which uses the Object.assign:
var obj = [{
id: 1,
value: 'abc'
}, {
id: 2,
value: 'xyz'
}];
console.log(Object.assign({}, obj));
it's getting transformed as,
{
'0': { id: 1, value: 'abc' },
'1': { id: 2, value: 'xyz' }
}
However I need to have this as, (here the 1 and 2 represents the id attribute of my object)
{
'1': {id: 1, value: 'abc'},
'2': {id: 2, value: 'xyz'}
}
I've tried few, but had no luck, Can someone shed some light?
You could map the objects in an object with the wanted key and assign it to a single object.
var objects = [{ id: 1, value: 'abc' }, { id: 2, value: 'xyz' }],
result = Object.assign(...objects.map(o => ({ [o.id]: o })));
console.log(result);
You can use reduce() method with Object.assign.
var obj = [{id: 1, value: 'abc'}, {id: 2, value: 'xyz'}];
var result = obj.reduce((r, e) => Object.assign(r, {[e.id]: e}), {});
console.log(result)
You can directly use Array#reduce to do that, and there is no need for Object.assign here:
var obj = [{id: 1, value: 'abc'}, {id: 2, value: 'xyz'}];
let result = obj.reduce((acc, item) => {
acc[item.id] = item;
return acc;
}, {});
console.log(result);
If you want to use .id to be the key, you can use reduce and use Object.assign
let obj = [{id: 1,value: 'abc'}, {id: 2,value: 'xyz'}];
let result = obj.reduce((c, v) => Object.assign(c, {[v.id]: v}), {});
console.log(result);

Categories

Resources