So, I have an array like this:
[
{ tags__region: "Stockholm" },
{ tags__region: "Lund" },
{ tags__region: "Mora" },
{ tags__user: "Johan" },
{ tags__user: "Eva" }
]
and I want to turn that into an object like this:
{
tags__region: ["Stockholm", "Lund", "Mora"],
tags__user: ["Johan", "Eva"]
}
Is there a way with lodash?
Are vanilla Array/Object -methods simple enough?
Keep in mind the keys on my array are unknown, so they are not always the same.
Simple Javascript.
let arr = [{
tags__region: "Stockholm"
},
{
tags__region: "Lund"
},
{
tags__region: "Mora"
},
{
tags__user: "Johan"
},
{
tags__user: "Eva"
}
];
arr = arr.reduce((acc, val) => {
let key = Object.keys(val)[0];
let value = Object.values(val)[0];
acc[key] = acc[key] ? [...acc[key],value] : [value]
return acc;
}, {})
console.log(arr);
You can use Lodash's _.mergeWith() with array spread to combine all items in the array to a single object. If the same property exists in two object, the values will be collected to an array:
const arr = [{"tags__region":"Stockholm"},{"tags__region":"Lund"},{"tags__region":"Mora"},{"tags__user":"Johan"},{"tags__user":"Eva"}]
const result = _.mergeWith({}, ...arr, (objValue = [], srcValue) =>
[...objValue, srcValue]
)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
With Lodash/fp you can generate a function (fn) using _.mergeAllWith(), and _.concat() that will do the same thing:
const fn = _.mergeAllWith(_.concat)
const arr = [{"tags__region":"Stockholm"},{"tags__region":"Lund"},{"tags__region":"Mora"},{"tags__user":"Johan"},{"tags__user":"Eva"}]
const result = fn(arr)
console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)'></script>
Related
I have [ { key1:value1, key2:value2 }, { key3:value3, key4:value4 }, .... ]. I want to convert it to
{ value1: value2, value3: value4 }
Use Array#reduce to accumulate your object-data. Foreach object take from the values the first and add a new property with this name to the accumulated object with the value from the second object-value.
let array = [ { key1:'value1', key2:'value2' }, { key3:'value3', key4:'value4' }];
let res = array.reduce((acc, cur) => {
values = Object.values(cur);
acc[values[0]] = values[1];
return acc;
}, {});
console.log(res);
Assuming the inner objects always have 2 keys:
const arr = [ { key1:'value1', key2:'value2' }, { key3:'value3', key4:'value4' }]
const obj = {};
for (const innerObj of arr) {
const values = Object.values(innerObj);
obj[values[0]] = values[1];
}
console.log(obj) // { value1: 'value2', value3: 'value4' }
Note: you're question assumes an order for the keys in the inner objects, but that may not be guaranteed
I have an object with key-value pair and its value as an array of elements.
{
status: ["new", "old"],
place: ["york", "blah"]
}
I'm trying to convert it into multiple array objects of key-value pair like below.
{
"newObj1": [
{ "status": "new" },
{ "status": "old" }],
"newObj2": [
{ "place": "york" },
{ "place": "blah" }]
}
Is there any way to achieve the above structure? I have tried couple of methods using array reduce methods but it doesn't give in the desired output.
let value= {
status: ["new", "old"],
place: ["york", "blah"]
}
Object.keys(value).map((key) => [key, value[key]]);
You can do something like this
const obj = {
status: ["new", "old"],
place: ["york", "blah"]
};
const result = {};
Object.keys(obj).forEach((key, index) => {
result[`newObj${index + 1}`] = obj[key].map(item => ({[key]: item}));
});
console.log(result);
Here's a solution that uses Array.reduce():
const value = {
status: ["new", "old"],
place: ["york", "blah"]
};
const result = Object.keys(value).reduce((acc, key, i) => {
acc["newObj" + (i + 1)] = value[key].map(k => ({ [key]: k }));
return acc;
}, {});
console.log(result);
Here is my way of accomplishing that.
let source = {
status: ["new", "old"],
place: ["york", "blah"]
};
let destination = {}; // make room for the destinoation object
Object.keys(source).forEach((key, index) => {
let obj = "newObj" + (index + 1); // assume all objects are named "newObj1,2,3,etc"
if (!destination[obj]) { // check if the object exists already
// if not, then crate an empty array first
destination[obj] = [];
}
// loop through all items in the source element array
source[key].forEach(value => {
// create an object from the array element
let subObj = {};
subObj[key] = value;
// push that object to the destination
destination[obj].push(subObj);
});
});
console.log(destination);
const data = {
status: ["new", "old"],
place: ["york", "blah"]
};
let result = Object.fromEntries( Object.entries(data).map( ([key, [first, second]], index) => {
return [ `newObj${index}`, [ { [key]: first }, { [key]: second } ] ];
} ) );
console.log(result);
Here's an idiomatic solution using .reduce inside .reduce:
Object.entries(data)
.reduce((result, [key, value], index) => !(result['newObj' + (index + 1)] = value
.reduce((arr, text) => !arr
.push({ [key]: text }) || arr, [])) || result, {});
Here's a live example:
const data = {
status: ['new', 'old'],
place: ['york', 'blah']
};
const result = Object.entries(data)
.reduce((result, [key, value], index) => !(result['newObj' + (index + 1)] = value
.reduce((arr, text) => !arr
.push({ [key]: text }) || arr, [])) || result, {});
console.log(result);
/*
{
newObj1: [
{ status: 'new' },
{ status: 'old' }
],
newObj2: [
{ place: 'york' },
{ place: 'blah' }
]
}
*/
For those who fail to understand map and reduce, here's a fairly naive solution but it will work:
newObjCounter = 1
orig = { status: [ 'new', 'old' ], place: [ 'york', 'blah' ] }
newObject = {}
//Initialise object with new keys with arrays as values
for(var key in orig){
newObject["newObj"+initialCounter] = []
initialCounter++
}
//Loop through keys of the original object and dynamically populate the new object
for(var key in orig){
index = "newObj"+objCounter
newObject[index].push({[key]:orig[key]})
objCounter++
}
console.log(newObject)
I've searched a lot for this but couldn't find anything that match my requirement.
I want to remove all the duplicates but keeping the last entry not the first.
The array is already presorted I don't want to mess with sorting
So it looks like this :
[{
name:"Joe",
status:"foo1" },
{
name:"Joe",
status:"foo2"},
{
name:"Vani",
status:"foo5"
}]
The expected output looks like:
[{
name:"Joe",
status:"foo2"},
{
name:"Vani",
status:"foo5"
}]
I'd be thankful if someone can help me!
You can simply use reduce
let arr = [{ name:"Joe", status:"foo1" }, { name:"Joe", status:"foo2"}, { name:"Vani", status:"foo5" }]
let op = arr.reduce((op,inp)=>{
op[inp.name] = inp
return op
},{})
console.log(Object.values(op))
You can make use of ES6 Map. As from Docs:
The Map object holds key-value pairs and remembers the original insertion order of the keys. Any value (both objects and primitive values) may be used as either a key or a value.
const data = [
{ name:"Joe", status:"foo1" },
{ name:"Joe", status:"foo2" },
{ name:"Vani", status:"foo5" }
];
const removeDupes = (arr, map = new Map()) => {
arr.forEach(o => map.set(o.name, o));
return [...map.values()];
};
console.log(removeDupes(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Try using simple forEach,
const arr = [{ name:"Joe", status:"foo1" }, { name:"Joe", status:"foo2"}, {
name:"Vani", status:"foo5" }];
let result = {};
arr.forEach((val) => { result[val.name] = val; });
console.log(Object.values(result));
Hope this helps...
The accepted answer doesn't actually keep the order, it amends the object at the initially found index
You could amend it to look like this:
const data = [
{ name:"Joe", status:"foo1" },
{ name:"Vani", status:"foo2" },
{ name:"Joe", status:"foo3" }
];
const removeDupes = (arr, map = new Map()) => {
arr.forEach((o, i) => map.set(o.name, {...o, order: i}));
return [...map.values()].sort((a, b) => a.order - b.order);
};
console.log(removeDupes(data));
Or perhaps do something more simple like:
const data = [
{ name:"Joe", status:"foo1" },
{ name:"Vani", status:"foo2" },
{ name:"Joe", status:"foo3" }
];
let newData = [];
data.forEach(x => {
newData = newData.filter(y => y.name != x.name);
newData.push(x);
});
console.log(newData);
I'll let someone else figure out a more performant solution...
At the entrance I have such an array with objects.
Function that converts an incoming array of objects into an object.
Using the function, I need to bring it to this form.
var array = [
{ k1:v1 },
{ k2:v2 },
{ k3:v3 }
];
function arrayToObject(array) { return object }
var object = {
v1: k1,
v2: k2,
v3: k3,
}
You could taske Object.assign and spread the reversed objects.
var array = [ { k1: 'v1' }, { k2: 'v2' }, { k3: 'v3' }],
object = Object.assign(...array.map(o => Object
.entries(o)
.reduce((r, [k, v]) => Object.assign(r, { [v] : k }), {})
));
console.log(object);
Use forEach loop
var array = [
{ k1:'v1' },
{ k2:'v2' },
{ k3:'v3' }
]
function a()
{
var obj={};
array.forEach((e)=>obj[e[Object.keys(e)[0]]]=Object.keys(e)[0])
console.log(obj)
}
a();
You can use Object.entries() and .reduce() methods to get the desired output:
const array = [
{ k1:'v1' },
{ k2:'v2' },
{ k3:'v3' }
];
const obj = Object.entries(
array.reduce((r, c) => Object.assign(r, c), {})
).reduce((r, [k, v]) => (r[v] = k, r), {});
console.log(obj);
Array.reduce and use Object.keys over each array element.
var array = [
{ k1: 'v1' },
{ k2: 'v2' },
{ k3: 'v3' }
]
var obj = array.reduce((obj, item) => {
Object.keys(item).forEach(key => obj[item[key]] = key)
return obj
}, {})
console.log(obj)
And another one:
const result = {};
for(const [[key, value]] of array.map(Object.entries))
result[value] = key;
I am not sure why the other answers go through hoops to make this as clever as possible.
I find this more readable. I am not using reduce because I find the word misleading. A simple forEach makes more sense to me
const array = [
{ k1:'v1' },
{ k2:'v2' },
{ k3:'v3' }
];
let newObj={};
array.forEach((obj) => {
let key = Object.keys(obj)[0];
newObj[obj[key]]=key;
})
console.log(newObj)
your answer..
var array = [
{ k1: v1 },
{ k2: v2 },
{ k3: v3 }
];
function arrayToObject(array) {
obj = {};
for (i = 0; i < array.length; i++) {
o = array[i];
key = Object.keys(o)[0];
obj.key = o.key;
}
return obj;
}
console.log(arrayToObject(array))
I have an array:
let ar = [
{
uid:1,
flat_no: 1
},
{
uid:2,
flat_no: 2
},
{
uid:1,
flat_no:3
}
];
If uid are same then I want to remove duplicate uid and concatenate its flat_no. The output array should be like this:
[
{
uid:1,
flat_no: [1,3]
},
{
uid:2,
flat_no: 2
}
];
You can use a combination of Array.reduce and Array.find.
If you find an existing item in your accumulator array, just update it's flat_no property, otherwise push it to the accumulator array.
let arr = [
{
uid: 1,
flat_no: 1
},
{
uid: 2,
flat_no: 2
},
{
uid: 1,
flat_no: 3
}
]
arr = arr.reduce((arr, item) => {
const existing = arr.find(innerItem => innerItem.uid === item.uid)
if (existing) {
existing.flat_no = Array.isArray(existing.flat_no)
? existing.flat_no
: [existing.flat_no]
existing.flat_no.push(item.flat_no)
} else {
arr.push(item)
}
return arr
}, [])
console.log(arr)
You can iterate over your array and fill an object (used as a hashmap here).
Once done, you extract the values to get your result.
let hashResult = {}
ar.forEach(element => {
if (hashResult[element.uid] == undefined) {
hashResult[element.uid] = { uid: element.uid, flat_no: [] }
}
hashResult[element.uid].flat_no.push(element.flat_no)
})
let result = Object.values(hashResult)
console.log(new Date(), result)
You can do this in a concise way with a single Array.reduce and Object.values to match your desired output:
let data = [ { uid:1, flat_no: 1 }, { uid:2, flat_no: 2 }, { uid:1, flat_no:3 } ];
const result = data.reduce((r, {uid, flat_no}) => {
r[uid] ? r[uid].flat_no = [r[uid].flat_no, flat_no] : r[uid] = {uid, flat_no}
return r
}, {})
console.log(Object.values(result))
1)Reduce the initial array to an object which has uid as the key and the flat_no as the value.
2)Then run a map on the keys to convert it into an array of objects with uid and flat_no.
1) First Step Code
let ar = [{uid:1, flat_no: 1},{uid:2, flat_no: 2},{uid:1, flat_no:3}];
let outputObj = ar.reduce((outputObj,currObj,currIndex) => {
let {uid,flat_no} = currObj
if (outputObj[uid]) {
outputObj[uid].push(flat_no)
}
else {
outputObj[uid] = [flat_no]
}
return outputObj
},{})
2)
let finalOutput = Object.keys(outputObj).map(key =>
({uid:key,flat_no:outputObj[key]}))
console.log(finalOutput)