I'm trying to construct an array of objects from a set of two different arrays. I'm a little comfussed on where I need to go from here.
I'm creating a unique key value, but the object is going into the array individual.
const startingArray = [
{
key: "description",
value: "my description"
},
{
key: "description2",
value: "my description2"
},
{
key: "description3",
value: "my description3"
},
]
my logic
const k = mystartingArray.reduce((acc, d, count) => {
const name = Object.value(d)[0]
const title = Object.value(d)[1]
const value = {
[name]: title
}
acc.push(value)
return acc
},[])
how I want the Array to look
const finishedArray = [
{
description: "my description",
description2: "my description2,
description3: "my description3,
}
How far am I off?
I think this would be simpler to solve just by using a basic forEach.
let value = {};
startingArray.forEach(obj => {
value[obj.key] = obj.value;
});
const finishedArray = [value];
Or, if you don't want to have a value object:
const finishedArray = [{}];
startingArray.forEach(obj => {
finishedArray[0][obj.key] = obj.value;
});
const finishedArray = [
startingArray.reduce((a, v) => {a[v.key] = v.value; return a}, {})
]
To finish your code:
const startingArray = [
{
key: "description",
value: "my description"
},
{
key: "description2",
value: "my description2"
},
{
key: "description3",
value: "my description3"
},
];
const k = startingArray.reduce((acc, d, count) => {
return [{
...(acc[0] || {}),
[d.key]: d.value
}]
},[])
console.log(k);
However, I think the solution of Rocket Hazmat is more reasonable than this.
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' } }
Hi all I have the following code
the data that I want to transform.
const obj = {
numbers: {
label: "main numbers",
pageTitle: "Numbers",
key: "1",
items: {
firstNumber: {
label: "first number",
pageTitle: "first",
key: "first"
},
secondNumber: {
label: "second number",
pageTitle: "second",
key: "second"
}
}
},
letters: {
label: "main Letters",
pageTitle: "Letters",
key: "2",
items: {
firstLetter: {
label: "first Letter",
pageTitle: "first",
key: "first"
}
}
},
signs: {
label: "main sign",
pageTitle: "Sign",
key: "3"
}
};
In my obj variable I have 3 other objects
numbers object which has items property which includes 2 other objects.
letters object which has items property which includes only one object.
signs object.
I need to transform my obj to the following way.
[
{
label:"main numbers",
pageTitle:"Numbers",
key:1,
children: [{label,pageTitle,key},{label,pageTitle,key}]
},
{
label:"main Letters",
pageTitle:"Letters",
key:1,
children: [{label,pageTitle,key}]
},
{
label:"main sign",
pageTitle:"Sign",
key:1,
children: []
},
]
for that transformation, I wrote the following code.
const transformedData = Object.values(obj).map((menuitem) => menuitem);
const data = [];
transformedData?.map((x) => {
const newData = {};
newData.label = x.label;
newData.pageTitle = x.pageTitle;
newData.key = x.key;
newData.children = x?.Object?.values(items)?.map((el) => {
newData.children.label = el.label;
newData.children.pageTitle = el.pageTitle;
newData.children.key = el.key;
});
data.push(newData);
});
Everything was working, but for children instead of printing an array it prints undefined.
Please help me to resolve this issue.
I created a function for your case.
const convert = data =>
Object.values(data)?.map(x => ({
label: x.label,
pageTitle :x.pageTitle ,
key: x.pathname,
children: x.items
? Object.values(x.items || {}).map(el => ({ label: el.label,
key:el.pathname,pageTitle:el.pageTitle }))
: null,
}));
You can use like const items = convert(obj).
xdoesn't have Objects. Change it to:
newData.children = Object.values(x.items)?.map(/*...*/);
Is this what you're after?
const transformedData = Object.values(obj).map((menuitem) => menuitem);
const data = [];
transformedData?.map((x) => {
const newData = {};
newData.label = x.label;
newData.pageTitle = x.pageTitle;
newData.key = x.key;
if(x.hasOwnProperty('items')){
newData.children = Object.values(x.items).map((el) => {
const obj={
label:el.label,
pageTitle:el.pageTitle,
key:el.key
}
return obj
})};
data.push(newData);
});
console.log(data)
Your code return undefined because inside map you didn't return anything so newData.children was never populated with anything.
Also, I think accessing and assigning newData.children.label was problematic since there was no newData.children yet. So we declare a temp obj inside map and we return it
Lastly we need to check if items is a property that exists in the first place.
I have a function that interacts with 2 arrays, 1st array is an array of objects that contain my dropdown options, second array is an array of values. I'm trying to filter the 1st array to return what has matched the values in my 2nd array. How do I achieve this?
1st Array:
const books = [
{
label: "To Kill a Mockingbird",
value: 1
},
{
label: "1984",
value: 2
},
{
label: "The Lord of the Rings",
value: 3
},
{
label: "The Great Gatsby",
value: 4
}
]
Code Snippet below:
const idString = "1,2,3";
function getSelectedOption(idString, books) {
const ids = idString.split(",");
const selectedOptions = [];
ids.map(e => {
const selected = books.map(options => {
if (options.value === e){
return {
label: options.label,
value: options.value
}
}
})
selectedOptions.push(selected)
})
return selectedOptions
}
Result:
[
[undefined, undefined, undefined, undefined],
[undefined, undefined, undefined, undefined],
[undefined, undefined, undefined, undefined]
]
Expected Result:
[
{
label: "To Kill a Mockingbird",
value: 1
},
{
label: "1984",
value: 2
},
{
label: "The Lord of the Rings",
value: 3
}
]
Assuming that value is unique, you can update your code as following to get them in order.
const idString = "1,2,3";
function getSelectedOption(idString, books) {
const ids = idString.split(",");
return ids.map(id => books.find(book => book.value == id)).filter(Boolean)
}
You can also filter the books array if you don't care about the order or in case that the value is not unique.
const idString = "1,2,3";
function getSelectedOption(idString, books) {
const ids = idString.split(",");
return books.filter(book => ids.includes(book.value.toString()))
}
Please note that these are O(n*m) algorithms and it should not be used with large sets of data, however if one of the arrays is relatively small you can use it.
function getSelectedOption(idString, books) {
const idArray = convertStringToArray(idString)
return books.filter(item => idString.includes(item.value))
}
function convertStringToArray(string) {
return string.split(",")
}
Using an array filter:
function getSelectedOption(idString, books) {
const ids = idString.split(",");
return books.filter((item) => ids.includes(item.value.toString()));
}
const books = [{
label: "To Kill a Mockingbird",
value: 1
},
{
label: "1984",
value: 2
},
{
label: "The Lord of the Rings",
value: 3
},
{
label: "The Great Gatsby",
value: 4
}
]
const idString = "1,2,3";
getSelectedOption(idString, books);
console.log(getSelectedOption(idString, books));
Some fixes to your solution
After split idString, it would result in array of string value, so you have to cast it to number
Instead of use map to get selected, you should use find
const books = [
{
label: 'To Kill a Mockingbird',
value: 1
},
{
label: '1984',
value: 2
},
{
label: 'The Lord of the Rings',
value: 3
},
{
label: 'The Great Gatsby',
value: 4
}
]
const idString = '1,2,3'
function getSelectedOption(idString, books) {
const ids = idString.split(',').map(Number)
const selectedOptions = []
ids.forEach(e => {
const selected = books
.map(options => {
if (options.value === e) {
return {
label: options.label,
value: options.value
}
}
})
.filter(options => options !== undefined)
selectedOptions.push(selected[0])
})
return selectedOptions
}
console.log(getSelectedOption(idString, books))
I have a JS array (shown 4 examples actual has 66 )
[["A","Example1"],["A","Example2"],["B","Example3"],["B","Example4"]]
that I am trying to get into an object for a multi select drop down menu:
var opt = [{
label: 'A', children:[
{"label":"Example1","value":"Example1","selected":"TRUE"},
{"label":"Example2","value":"Example2","selected":"TRUE"}
]
},
{
label: 'B', children:[
{"label":"Example3","value":"Example3","selected":"TRUE"},
{"label":"Example4","value":"Example4","selected":"TRUE"}
]
}
]
Is there a easy way to do this ?
Updated:
Using reduce() and filter() to get expected results.
const result = [['A', 'Example1'], ['A', 'Example2'], ['B', 'Example3'], ['B', 'Example4']].reduce((acc, cur) => {
const objFromAccumulator = acc.filter((row) => row.label === cur[0]);
const newChild = {label: cur[1], value: cur[1], selected: 'TRUE'};
if (objFromAccumulator.length) {
objFromAccumulator[0].children.push(newChild);
} else {
acc.push({label: cur[0], children: [newChild]});
}
return acc;
}, []);
console.log(result);
Something like this should work:
const raw = [["A","Example1"],["A","Example2"],["B","Example3"],["B","Example4"]];
const seen = new Map();
const processed = raw.reduce((arr, [key, label]) => {
if (!seen.has(key)) {
const item = {
label: key,
children: []
};
seen.set(key, item);
arr.push(item);
}
seen.get(key).children.push({
label,
value: label,
selected: "TRUE"
})
return arr;
}, []);
console.log(processed);
Here's a rather efficient and concise take on the problem using an object as a map:
const data = [["A","Example1"],["A","Example2"],["B","Example3"],["B","Example4"]];
const opt = data.reduce((results,[key,val]) => {
if(!results[0][key]) //first element of results is lookup map of other elements
results.push(results[0][key] = { label: key, children: [] });
results[0][key].children.push({ label: val, value: val, selected:"TRUE" });
return results;
}, [{}]).slice(1); //slice off map as it's no longer needed
console.log(opt);
I have an example:
var A = [{
key: "iphone",
value: "American"
}, {
key: "sony",
value: "Japan"
}]
I want to do this action:
B=[{value:"American"},{value:"Japan"}]
How can I do this? Help me.
Use Array.map and return a new Object with the value field,
DEMO
var A =[{key:"iphone",value:"American"},{key:"sony",value:"Japan"}] ;
var result = A.map(d => ({ value: d.value }));
console.log(result);
var B = A.map(function(obj) { return { value: obj.value }; });
or
var B = A.map(obj => ({ value: obj.value }));
Maybe you prefer this more readable syntax?
function myObjectConverter (inputObject) {
var outputObject = {};
// ignore the key property
outputObject.Country1 = inputObject.value1;
outputObject.Country2 = inputObject.value2;
outputObject.Country3 = inputObject.value3;
outputObject.Country4 = inputObject.value4;
// transfer any other items with new names
return outputObject;
}
var B = A.map(myObjectConverter);