Related
I have an array of objects:
[
{ key : '11', value : '1100', $$hashKey : '00X' },
{ key : '22', value : '2200', $$hashKey : '018' }
];
How do I convert it into the following by JavaScript?
{
"11": "1100",
"22": "2200"
}
Tiny ES6 solution can look like:
var arr = [{key:"11", value:"1100"},{key:"22", value:"2200"}];
var object = arr.reduce(
(obj, item) => Object.assign(obj, { [item.key]: item.value }), {});
console.log(object)
Also, if you use object spread, than it can look like:
var object = arr.reduce((obj, item) => ({...obj, [item.key]: item.value}) ,{});
One more solution that is 99% faster is(tested on jsperf):
var object = arr.reduce((obj, item) => (obj[item.key] = item.value, obj) ,{});
Here we benefit from comma operator, it evaluates all expression before comma and returns a last one(after last comma). So we don't copy obj each time, rather assigning new property to it.
This should do it:
var array = [
{ key: 'k1', value: 'v1' },
{ key: 'k2', value: 'v2' },
{ key: 'k3', value: 'v3' }
];
var mapped = array.map(item => ({ [item.key]: item.value }) );
var newObj = Object.assign({}, ...mapped );
console.log(newObj );
One-liner:
var newObj = Object.assign({}, ...(array.map(item => ({ [item.key]: item.value }) )));
You're probably looking for something like this:
// original
var arr = [
{key : '11', value : '1100', $$hashKey : '00X' },
{key : '22', value : '2200', $$hashKey : '018' }
];
//convert
var result = {};
for (var i = 0; i < arr.length; i++) {
result[arr[i].key] = arr[i].value;
}
console.log(result);
I like the functional approach to achieve this task:
var arr = [{ key:"11", value:"1100" }, { key:"22", value:"2200" }];
var result = arr.reduce(function(obj,item){
obj[item.key] = item.value;
return obj;
}, {});
Note: Last {} is the initial obj value for reduce function, if you won't provide the initial value the first arr element will be used (which is probably undesirable).
https://jsfiddle.net/GreQ/2xa078da/
Using Object.fromEntries:
const array = [
{ key: "key1", value: "value1" },
{ key: "key2", value: "value2" },
];
const obj = Object.fromEntries(array.map(item => [item.key, item.value]));
console.log(obj);
A clean way to do this using modern JavaScript is as follows:
const array = [
{ name: "something", value: "something" },
{ name: "somethingElse", value: "something else" },
];
const newObject = Object.assign({}, ...array.map(item => ({ [item.name]: item.value })));
// >> { something: "something", somethingElse: "something else" }
you can merge array of objects in to one object in one line:
const obj = Object.assign({}, ...array);
Use lodash!
const obj = _.keyBy(arrayOfObjects, 'keyName')
Update: The world kept turning. Use a functional approach instead.
Previous answer
Here you go:
var arr = [{ key: "11", value: "1100" }, { key: "22", value: "2200" }];
var result = {};
for (var i=0, len=arr.length; i < len; i++) {
result[arr[i].key] = arr[i].value;
}
console.log(result); // {11: "1000", 22: "2200"}
Simple way using reduce
// Input :
const data = [{key: 'value'}, {otherKey: 'otherValue'}];
data.reduce((prev, curr) => ({...prev, ...curr}) , {});
// Output
{key: 'value', otherKey: 'otherValue'}
More simple Using Object.assign
Object.assign({}, ...array);
Using Underscore.js:
var myArray = [
Object { key="11", value="1100", $$hashKey="00X"},
Object { key="22", value="2200", $$hashKey="018"}
];
var myObj = _.object(_.pluck(myArray, 'key'), _.pluck(myArray, 'value'));
Nearby 2022, I like this approach specially when the array of objects are dynamic which also suggested based on #AdarshMadrecha's test case scenario,
const array = [
{ key : '11', value : '1100', $$hashKey : '00X' },
{ key : '22', value : '2200', $$hashKey : '018' }];
let obj = {};
array.forEach( v => { obj[v.key] = v.value }) //assign to new object
console.log(obj) //{11: '1100', 22: '2200'}
let array = [
{ key: "key1", value: "value1" },
{ key: "key2", value: "value2" },
];
let arr = {};
arr = array.map((event) => ({ ...arr, [event.key]: event.value }));
console.log(arr);
Was did yesterday
// Convert the task data or array to the object for use in the above form
const {clientData} = taskData.reduce((obj, item) => {
// Use the clientData (You can set your own key name) as the key and the
// entire item as the value
obj['clientData'] = item
return obj
}, {});
Here's how to dynamically accept the above as a string and interpolate it into an object:
var stringObject = '[Object { key="11", value="1100", $$hashKey="00X"}, Object { key="22", value="2200", $$hashKey="018"}]';
function interpolateStringObject(stringObject) {
var jsObj = {};
var processedObj = stringObject.split("[Object { ");
processedObj = processedObj[1].split("},");
$.each(processedObj, function (i, v) {
jsObj[v.split("key=")[1].split(",")[0]] = v.split("value=")[1].split(",")[0].replace(/\"/g,'');
});
return jsObj
}
var t = interpolateStringObject(stringObject); //t is the object you want
http://jsfiddle.net/3QKmX/1/
// original
var arr = [{
key: '11',
value: '1100',
$$hashKey: '00X'
},
{
key: '22',
value: '2200',
$$hashKey: '018'
}
];
// My solution
var obj = {};
for (let i = 0; i < arr.length; i++) {
obj[arr[i].key] = arr[i].value;
}
console.log(obj)
You can use the mapKeys lodash function for that. Just one line of code!
Please refer to this complete code sample (copy paste this into repl.it or similar):
import _ from 'lodash';
// or commonjs:
// const _ = require('lodash');
let a = [{ id: 23, title: 'meat' }, { id: 45, title: 'fish' }, { id: 71, title: 'fruit' }]
let b = _.mapKeys(a, 'id');
console.log(b);
// b:
// { '23': { id: 23, title: 'meat' },
// '45': { id: 45, title: 'fish' },
// '71': { id: 71, title: 'fruit' } }
say that I receive this JSON array from an API call.
[
"{'apple': 'enabled'}",
"{'banana': 'disabled'}"
]
How do I transform it into this:
[
{
label: 'apple',
value: 'enabled'
},
{
label: 'banana',
value: 'disabled'
}
]
The number of fields and the values are of course variable.
With JSON5.parse() I can transform it into this:
[
{
apple: 'enabled',
},
{
banana: 'disabled'
}
]
But this is still not what I need.
How can I achieve the transformation I need, without hacky workarounds that might change the values inside?
Thank you
const apiArray = [
"{'apple': 'enabled'}",
"{'banana': 'disabled'}"
];
const returnArray = [];
for (const element of apiArray) {
const parsedObj = JSON.parse(element);
const label = Object.keys(element)[0];
const value = parsedObj[label];
returnArray.push({"label": label, "value": value});
}
This inspects every element of the initial array on its own and extracts the label and the value. These then get pushed into the returnArray in the correct format.
I managed to make it work with this:
(Thanks #Alexander)
data.map(el=>{
const parsed = JSON5.parse(el)
return{
label: Object.keys(parsed)[0],
value: Object.values(parsed)[0]
}
})
However, it is not very clean.
you can try this
var newArr = [];
apiArray.forEach((element) => {
let obj = JSON.parse(element.replaceAll("'", '"'));
newArr.push({ label: Object.keys(obj)[0], value: Object.values(obj)[0] });
});
console.log(JSON.stringify(newArr));
you can try something like this :
myArray.map((data) => {
const parsedData = JSON.parse(data);
return {
label: Object.keys(parsedData).join(),
value: Object.values(parsedData).join(),
};
});
Output :
[{
"label": "apple",
"value": "enabled"
},
{
"label": "banana",
"value": "disabled"
}]
I have two arrays as listed below. I'm trying to create a new array of objects by using the field key in array_1 and the values in array_2.
const result = []
array_1 = [{ name: "Color" , field: "color"}, {name: "Shape", field: "shape" }, { name: "Whatever", field: "whatever" }]
array_2 = [["green", "rectangular", "whatever1"], ["yellow", "circle", "whatever2"]]
The result should be:
console.log(result)
// [{color:"green", shape:"rectangular", whatever: "whatever1"},
// { color:"yellow", shape: "circle", whatever:"whatever2"}]
I did this at my final trial:
const rowObj = {}
const result = array.map((subarray) => subarray.map((cell, index) => {
console.log(cell,index)
rowObj[columns[index].field] = cell
return rowObj
}))
Basically, I was overwriting the same object.
Thanks,
One way to do it is to map() over the array_2 and in each iteration:
Create a new object
Iterate over the array_1 to fill the newly created object. You can use the index parameter of the forEach() method's callback function to get the field property from the objects inside array_1.
and then return that object from the callback function of the map() method.
const array_1 = [
{ name: 'Color', field: 'color' },
{ name: 'Shape', field: 'shape' },
{ name: 'Whatever', field: 'whatever' },
];
const array_2 = [
['green', 'rectangular', 'whatever1'],
['yellow', 'circle', 'whatever2'],
];
const result = array_2.map(arr => {
const o = {};
arr.forEach((str, idx) => {
o[array_1[idx].field] = str;
});
return o;
});
console.log(result);
You can use array.map to iterate both arrays and take advantage of Object.fromEntries to build new objects based on the order of array elements:
array_1 = [{ name: "Color" , field: "color"}, {name: "Shape", field: "shape" }, { name: "Whatever", field: "whatever" }]
array_2 = [["green", "rectangular", "whatever1"], ["yellow", "circle", "whatever2"]]
let result = array_2.map(
x => Object.fromEntries(
array_1.map((y,i) => ([y.field, x[i]]))))
console.log(result);
Explanation
You could create a function that creates a constructor based on the descriptions of your object's fields like this:
function createConstructor(fieldsDescriptor) {
return function(fields) {
fieldsDescriptor.forEach((descriptor, index) => {
this[descriptor.field] = fields[index]
})
}
}
Then you could, for example, make a sampleConstructor that creates objects based on the field names of array_1:
const SampleConstructor = createConstructor(array_1)
And then, for each entry in array_2 you could apply your SampleConstructor:
const result = array_2.map(fields => new SampleConstructor(fields))
Motivation
Creating a dedicated constructor adds some clear semantics to your app, shows readers what you are doing and also stores constructor information in the created objects at runtime.
When you later want to know which constructor made which objects you can just call object.constructor and use this information to determine what kind of objects they are.
For example calling result[0].constructor == SampleConstructor will be true because SampleConstructor is the constructor that created the first result.
Demo
Here is a full demo
const array_1 = [{ name: "Color" , field: "color"}, {name: "Shape", field: "shape" }, { name: "Whatever", field: "whatever" }]
const array_2 = [["green", "rectangular", "whatever1"], ["yellow", "circle", "whatever2"]]
function createConstructor(fieldsDescriptor) {
return function(fields) {
fieldsDescriptor.forEach((descriptor, index) => {
this[descriptor.field] = fields[index]
})
}
}
const SampleConstructor = createConstructor(array_1)
const results = array_2.map(fields => new SampleConstructor(fields))
console.log(results)
const EmptyConstructor = createConstructor([])
console.log(results[0].constructor == SampleConstructor)
console.log(results[0].constructor == EmptyConstructor)
You can try this
array_1 = [
{ name: 'Color', field: 'color' },
{ name: 'Shape', field: 'shape' },
{ name: 'Whatever', field: 'whatever' }
];
array_2 = [
['green', 'rectangular', 'whatever1'],
['yellow', 'circle', 'whatever2']
];
const keys = array_1.map(item => item.field);
const output = [];
array_2.forEach(item => {
const temp = {};
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const value = item[i];
temp[key] = value;
}
output.push(temp);
});
console.log(output);
How do I set deep properties in a JavaScript object using a dot-syntax string to specify which property I want to change?
For simple objects, I could just use data['property_name'] = 'foo', but I don't necessarily know how deeply nested the data is going to be.
Below is some example code with how I'd like to be able to format the data in the end. For all I know there's a nice way that JS already allows you to do this, but I haven't been able to find it yet.
Plunker here.
var items = [
{
lookup_string: "User.UserProfile.name",
value: "John Smith"
},
{
lookup_string: "User.email",
value: "johnsmith#example.com"
},
]
var data = {};
items.forEach(function(item){
// Inside this loop, set the appropriate keys under data. Is there a non-convoluted way to do this?
});
console.log("items", items);
console.log("Results", data)
// In the end, data should look like this:
var desiredData = {
User: {
UserProfile: {
name: 'John Smith'
},
email: 'johnsmith#example.com'
}
}
You could split the lookup_string and reduce an object with a default object. Later assign the value.
function setValue(object, path, value) {
var keys = path.split('.'),
last = keys.pop();
keys.reduce(function (o, k) {
return o[k] = o[k] || {};
}, object)[last] = value;
}
var items = [{ lookup_string: "User.UserProfile.name", value: "John Smith" }, { lookup_string: "User.email", value: "johnsmith#example.com" }],
object = {};
items.forEach(function(o) {
setValue(object, o.lookup_string, o.value);
});
console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }
you will have to loop over all the keys from lookup_string.split('.') and assign values, something like this:
var items = [
{
lookup_string: "User.UserProfile.name",
value: "John Smith"
},
{
lookup_string: "User.email",
value: "johnsmith#example.com"
},
];
var data = {};
items.forEach(function(item){
var lookup = item.lookup_string.split('.');
var lastKey;
lookup.map(function(key){
data[key] = {};
lastKey = key;
});
data[lastKey] = item.value;
});
console.log("items", items);
console.log("Results", data)
// In the end, data should look like this:
var desiredData = {
User: {
UserProfile: {
name: 'John Smith'
},
email: 'johnsmith#example.com'
}
};
This is my code..
var result = data.map(function(item){
return {
category:item.category,
key:item.key,
value:item.value
}
});
console.log(result);
This is what is getting printed out in console..
Array[4]
0: Object
category: "common"
key: "Food"
value: "food"
1: Object
category: "welcome"
key: "title"
value: "Welcome..."
2: Object
category: "welcome"
key: "app_description"
value: "In this App "
3: Object
category: "welcome"
key: "select_location"
value: "Select Location"
This is what I'm trying to achieve
{
common:{
"Food" : "food"
},
welcome:{
title : Welcome...,
app_description : "In this App",
select_location : "Select Location"
}
}
This is the code I'm trying .but it is not working..
return {
item.category:{
item.key:item.value;
}
Can anyone help me with this? I dont want to use GSON or any other third-party JS..How can i get this done using only core JS?
First of all, what you want as a result is an object, not an array. So you can't use .map() which only maps one array to another array.
You want .reduce().
var result = data.reduce(function (result, item) {
// Create the object the first time it arrives
result[item.category] = result[item.category] || {};
// Add the field
result[item.category][item.key]=item.value;
// Return the resulting object
return result;
}, {});
console.log(result);
.reduce()'s reduction function takes two (with 2 more optional) parameters. The cumulative result, and the current item. The returned value is the result after the current item has been processed on it.
The second parameter for .reduce() (the first being the reduction function), is the initial value, this value will get passed as result for the first iteration.
Array.prototype.reduce() comes to rescue.
var result = data.reduce(function (previousValue, currentValue) {
previousValue[currentValue.category] = previousValue[currentValue.category] || {};
previousValue[currentValue.category][currentValue.key] = currentValue.value;
return previousValue;
}, {});
you can also try:
var data = [
{
category: "common",
key: "Food",
value: "food"
},
{
category: "welcome",
key: "title",
value: "Welcome..."
},
{
category: "welcome",
key: "app_description",
value: "In this App "
},
{
category: "welcome",
key: "select_location",
value: "Select Location"
}
];
var obj = {};
for (var i in data) {
if(!obj[data[i].category]){
obj[data[i].category] = {};
}
obj[data[i].category][data[i].key] = data[i].value;
}
console.log(obj);