How to map an array to object - javascript

Is there a built-in lodash function to take this:
let params = ['foo', 'bar', 'baz', 'zle'];
let newArray = [];
params.forEach((element, index) => {
let key = "name" + index;
newArray.push({ key: element })
});
console.log(newArray);
And expected output should be like this:
var object = {
a: {
name1: "foo",
name2: "bar",
},
b: {
name1: "baz",
name2: "zle",
}
}

May this help you. I know that you should provide more information that what do really want to implement. but i got an idea that might help you.
let params = ['foo', 'bar', 'baz', 'zle'];
const keys = ['a', 'b', 'c', 'd']
let data = {}
while(params.length){
const [a, b] = params.splice(0, 2)
const key = keys.splice(0, 1)
data[key] = {
name1: a,
name2: b,
}
}
console.log(data)
output will be:
{
a: {
name1: "foo",
name2: "bar",
},
b: {
name1: "baz",
name2: "zle",
}
}

You can convert your array into Json like format that can be done like this
var jsonObj = {};
for (var i = 0 ; i < sampleArray.length; i++) {
jsonObj["position" + (i+1)] = sampleArray[i];
}

I have solved the issue. Solution for this issue is
let colLength = 4;
let breakableArray = _.chunk(data, 4);
breakableArray.forEach((arrayObject,key)=>{
let object = new Object();
for(let i = 0; i < colLength; i++) {
object[i] = arrayObject[i] != undefined ? arrayObject[i] : "-";
}
finalObject[key] = object;
})

Related

change key/values of an object

If I have a result like this:
result = [
{ '0': 'grade', A: 'name', b1: 'number' },
{ '1': 'grade', B: 'name', b2: 'number' },
{ '2': 'grade', C: 'name', b3: 'number' }
];
How can I produce :
result = [
{ A: '0', b1: '0' },
{ B: '1', b2: '1' },
{ C: '2', b3: '2' }
];
I want to pass the analogous grade instead of name and number.
The order of keys in an object is not guaranteed. This means simply getting a key array and looping through them or accessing them by index will not work. You could make this work be detecting numeric and non-numeric keys like so:
result = [
{ '0': 'grade', A: 'name', b1: 'number' },
{ '1': 'grade', B: 'name', b2: 'number' },
{ '2': 'grade', C: 'name', b3: 'number' }
];
result.forEach(item => {
var keys = Object.keys(item);
var numericKey = keys.find(key => !isNaN(key));
var nonNumericKeys = keys.filter(key => isNaN(key));
nonNumericKeys.forEach(nonNumKey => item[nonNumKey] = numericKey);
delete item[numericKey];
});
Assuming the b3: '1' part is a typo... the following should work.
var input = [
{ '0': 'grade', A: 'name', b1: 'number' },
{ '1': 'grade', B: 'name', b2: 'number' },
{ '2': 'grade', C: 'name', b3: 'number' }
];
function reverseMap(obj){
var newObj = {};
var keys = Object.keys(obj);
for(var i=0; i<keys.length; i++){
var k = keys[i];
var v = obj[k];
newObj[v] = k;
}
return newObj;
}
var output = [];
for(var i=0; i<input.length; i++){
var reverseObj = reverseMap(input[i]);
var outputObj = {};
var number = reverseObj.grade;
outputObj[reverseObj.name] = number;
outputObj[reverseObj.number] = number;
output.push(outputObj);
}
console.log(output);
With ES6 you can use the for of loop and Objects.keys for this task:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/let
let newResult = [];
for(let r of result) {
let keys = Object.keys(r);
let obj = {};
for(let key of keys) {
if(/\d/.test(key)) { var value = key; }
else if(/\w/.test(key)) { var key1 = key; }
else if(/\d/.test(key)) { var key2 = key; }
}
obj[key1] = value;
obj[key2] = value;
newResult.push(obj);
}
return newResult;

Combining arrays for use cases

Node.js app, writing validation tests. Given the following:
var obj = { foo: null, bar: null, baz: null},
values = [ 0, 1];
I need to create n number of objects to account for every property being assigned every combination of possible values, to represent every possible use case. So for this example, the output should be 2^3=8 objects, e.g.
[
{ foo: 0, bar: 0, baz: 0},
{ foo: 0, bar: 1, baz: 0},
{ foo: 0, bar: 1, baz: 1},
{ foo: 0, bar: 0, baz: 1},
{ foo: 1, bar: 0, baz: 0},
{ foo: 1, bar: 1, baz: 0},
{ foo: 1, bar: 1, baz: 1},
{ foo: 1, bar: 0, baz: 1},
]
Underscore or lodash or other libraries are acceptable solutions. Ideally, I would like something like so:
var mapUseCases = function(current, remaining) {
// using Underscore, for example, pull the current case out of the
// possible cases, perform logic, then continue iterating through
// remaining cases
var result = current.map(function(item) {
// perform some kind of logic, idk
return magic(item);
});
return mapUseCases(result, _.without(remaining, current));
}
var myValidationHeadache = mapUseCases(currentThing, somethingElse);
Pardon my pseudocode, I think I broke my brain. ¯\_(ツ)_/¯
Solution for any object length and any values.
Please note, undefined values do not show up.
function buildObjects(o) {
var keys = Object.keys(o),
result = [];
function x(p, tupel) {
o[keys[p]].forEach(function (a) {
if (p + 1 < keys.length) {
x(p + 1, tupel.concat(a));
} else {
result.push(tupel.concat(a).reduce(function (r, b, i) {
r[keys[i]] = b;
return r;
}, {}));
}
});
}
x(0, []);
return result;
}
document.write('<pre>' + JSON.stringify(buildObjects({
foo: [0, 1, 2],
bar: [true, false],
baz: [true, false, 0, 1, 42]
}), 0, 4) + '</pre>');
One way is to count from "000" to "999" in a values.length-based system:
keys = ['foo','bar','baz']
values = ['A', 'B']
width = keys.length
base = values.length
out = []
for(var i = 0; i < Math.pow(base, width); i++) {
var d = [], j = i;
while(d.length < width) {
d.unshift(j % base)
j = Math.floor(j / base)
}
var p = {};
for(var k = 0; k < width; k++)
p[keys[k]] = values[d[k]]
out.push(p)
}
document.write('<pre>'+JSON.stringify(out,0,3))
Update for products:
'use strict';
let
keys = ['foo', 'bar', 'baz'],
values = [
['A', 'B'],
['a', 'b', 'c'],
[0, 1]
];
let zip = (h, t) =>
h.reduce((res, x) =>
res.concat(t.map(y => [x].concat(y)))
, []);
let product = arrays => arrays.length
? zip(arrays[0], product(arrays.slice(1)))
: [[]];
let combine = (keys, values) =>
keys.reduce((res, k, i) =>
(res[k] = values[i], res)
, {});
let z = product(values).map(v => combine(keys, v));
z.map(x => document.write('<pre>'+JSON.stringify(x)+'</pre>'))
This is a non-recursive version of what you want:
function createRange(keys, values) {
if (typeof values[0] !== typeof [])
values = keys.map(k => values);
var pointer = {};
var repeats = 1;
keys.forEach((k, i) => {
var vLen = values[i].length;
repeats *= vLen;
pointer[k] = {
get value() {
return values[i][pointer[k].current]
},
current: 0,
period: Math.pow(vLen, i),
inc: function() {
var ptr = pointer[k];
ptr.current++;
if (ptr.current < vLen) return;
ptr.current = 0;
if (i + 1 === keys.length) return;
var nk = keys[i + 1];
pointer[nk].inc()
}
};
});
var result = [];
for (var i = 0; i < repeats; i++) {
var o = {};
result.push(o);
keys.forEach(k => o[k] = pointer[k].value)
pointer[keys[0]].inc();
}
return result;
}
var objKeys = ['u', 'v', 'w', 'x', 'y', 'z'];
var objValues = [
['1', '2', '3'],
['a', 'b', 'c'],
['foo', 'bar', 'baz'],
[1, 3, 2],
['test', 'try', 'catch'],
['Hello', 'World'],
];
var range = createRange(objKeys, objValues);
range.map(v => document.write(JSON.stringify(v).big()))

Flatten array with objects into 1 object

Given input:
[{ a: 1 }, { b: 2 }, { c: 3 }]
How to return:
{ a: 1, b: 2, c: 3 }
For arrays it's not a problem with lodash but here we have array of objects.
Use Object.assign:
let merged = Object.assign(...arr); // ES6 (2015) syntax
var merged = Object.assign.apply(Object, arr); // ES5 syntax
Note that Object.assign is not yet implemented in many environment and you might need to polyfill it (either with core-js, another polyfill or using the polyfill on MDN).
You mentioned lodash, so it's worth pointing out it comes with a _.assign function for this purpose that does the same thing:
var merged = _.assign.apply(_, [{ a: 1 }, { b: 2 }, { c: 3 }]);
But I really recommend the new standard library way.
With lodash, you can use merge():
var arr = [ { a: 1 }, { b: 2 }, { c: 3 } ];
_.merge.apply(null, [{}].concat(arr));
// → { a: 1, b: 2, c: 3 }
If you're doing this in several places, you can make merge() a little more elegant by using partial() and spread():
var merge = _.spread(_.partial(_.merge, {}));
merge(arr);
// → { a: 1, b: 2, c: 3 }
Here is a version not using ES6 methods...
var arr = [{ a: 1 }, { b: 2 }, { c: 3 }];
var obj = {};
for(var i = 0; i < arr.length; i++) {
var o = arr[i];
for(var key in o) {
if(typeof o[key] != 'function'){
obj[key] = o[key];
}
}
}
console.log(obj);
fiddle: http://jsfiddle.net/yaw3wbb8/
You can use underscore.extend function like that:
var _ = require('underscore');
var a = [{ a: 1 }, { b: 2 }, { c: 3 }];
var result = _.extend.apply(null, a);
console.log(result); // { a: 1, b: 2, c: 3 }
console.log(a); // [ { a: 1, b: 2, c: 3 }, { b: 2 }, { c: 3 } ]
And to prevent modifying original array you should use
var _ = require('underscore');
var a = [{ a: 1 }, { b: 2 }, { c: 3 }];
var result = _.extend.apply(null, [{}].concat(a));
console.log(result); // { a: 1, b: 2, c: 3 }
console.log(a); // [ { a: 1 }, { b: 2 }, { c: 3 } ]
Here can test it
Adding to the accepted answer, a running code snippet with ES6.
let input = [{ a: 1 }, { b: 2 }, { c: 3 }]
//Get input object list with spread operator
console.log(...input)
//Get all elements in one object
console.log(Object.assign(...input))
I've got a neat little solution not requiring a polyfill.
var arr = [{ a: 1 }, { b: 2 }, { c: 3 }];
var object = {};
arr.map(function(obj){
var prop = Object.getOwnPropertyNames(obj);
object[prop] = obj[prop];
});
Hope that helps :)
Here is a nice usage of Object.assign with the array.prototype.reduce function:
let merged = arrOfObjs.reduce((accum, val) => {
Object.assign(accum, val);
return accum;
}, {})
This approach does not mutate the input array of objects, which could help you avoid difficult to troubleshoot problems.
With more modern spread operator
arrOfObj.reduce( (acc, curr) => ({ ...acc, ...cur }) );
You can easily flat your object to array.
function flatten(elements) {
return elements.reduce((result, current) => {
return result.concat(Array.isArray(current) ? flatten(current) : current);
}, []);
};
6 years after this question was asked.
Object.assign is the answer (above) I like the most.
but is this also legal ?
let res = {};
[{ a: 1 }, { b: 2 }, { c: 3 }].forEach(val => {
let key = Object.keys(val);
console.log(key[0]);
res[key] = val[key];
})
const data = [
[{ a: "a" }, { b: "b" }, { c: "c" }],
[{ d: "d" }, { e: "e" }, { f: "f" }],
[{ g: "g" }, { h: "h" }, { i: "i" }],
];
function convertToObject(array){
const response = {};
for (let i = 0; i < array.length; i++) {
const innerArray = array[i];
for (let i = 0; i < innerArray.length; i++) {
const object = innerArray[i];
const keys = Object.keys(object);
for (let j = 0; j < keys.length; j++) {
const key = keys[j];
response[key] = object[key];
}
}
}
return response;
}
console.log(convertToObject(data));
function carParts(manufacturer, model, ...parts) {
return { manufacturer, model, ...Object.assign(...parts) };
}
console.log(
carParts(
"Honda",
"2008",
{ color: "Halogen Lights" },
{ Gears: "Automatic Gears" },
{ LED: "Android LED" },
{ LED: "Android LED1" }
)
);
This is how i have done.

Nested duplicate arrays in objects

I am trying to take an array of objects and do 2 things.
1.) Remove objects from the array that are duplicated, create a new array with the names of the items that were duplicates.
Original:
var duplicates = [];
var objects = [
{
name: 'foo',
nums: [1,2]
},
{
name: 'bar',
nums: [3,2]
},
{
name: 'baz',
nums: [1,2]
},
{
name: 'bum',
nums: [2,3]
},
{
name: 'bam',
nums: [1,2]
},
]
Desired Output:
duplicates = ['foo', 'baz', 'bam'];
objects = [
{
name: 'bar',
nums: [3,2]
},
{
name: 'bum',
nums: [2,3]
}
]
Can anyone help with this? I am using lodash in my project.
If order of elements in nums array matters:
_.pluck(_.flatten(_.filter(_.groupBy(objects, "nums"), function(el) {
return (el.length !== 1)
})), "name")
or a bit tidier
var hmap = _(objects).groupBy("nums").values();
var unique = hmap.where({'length': 1}).flatten().value();
var duplicates = hmap.flatten().difference(unique).value();
I don't know underscore.js, here's how to do it with plain JS:
var counts = {};
var duplicates = [];
for (var i = 0; i < objects.length; i++) {
var str = JSON.stringify(objects[i].nums);
if (str in counts) {
counts[str]++;
} else {
counts[str] = 1;
}
}
objects = objects.filter(function(val) {
if (counts[JSON.stringify(val.nums)] == 1) {
return true;
} else {
duplicates.push(val.name);
return false;
}
});
DEMO

Concatenate two JSON objects

I have two JSON objects with the same structure and I want to concat them together using Javascript. Is there an easy way to do this?
Based on your description in the comments, you'd simply do an array concat:
var jsonArray1 = [{'name': "doug", 'id':5}, {'name': "dofug", 'id':23}];
var jsonArray2 = [{'name': "goud", 'id':1}, {'name': "doaaug", 'id':52}];
jsonArray1 = jsonArray1.concat(jsonArray2);
// jsonArray1 = [{'name': "doug", 'id':5}, {'name': "dofug", 'id':23},
//{'name': "goud", 'id':1}, {'name': "doaaug", 'id':52}];
If you'd rather copy the properties:
var json1 = { value1: '1', value2: '2' };
var json2 = { value2: '4', value3: '3' };
function jsonConcat(o1, o2) {
for (var key in o2) {
o1[key] = o2[key];
}
return o1;
}
var output = {};
output = jsonConcat(output, json1);
output = jsonConcat(output, json2);
Output of above code is{ value1: '1', value2: '4', value3: '3' }
The actual way is using JS Object.assign.
Object.assign(target, ...sources)
MDN Link
There is another object spread operator which is proposed for ES7 and can be used with Babel plugins.
Obj = {...sourceObj1, ...sourceObj2}
I use:
let x = { a: 1, b: 2, c: 3 }
let y = {c: 4, d: 5, e: 6 }
let z = Object.assign(x, y)
console.log(z)
// OUTPUTS:
{ a:1, b:2, c:4, d:5, e:6 }
From here.
You can use jquery extend method.
Example:
o1 = {"foo":"bar", "data":{"id":"1"}};
o2 = {"x":"y"};
sum = $.extend(o1, o2);
Result:
sum = {"foo":"bar", "data":{"id":"1"}, "x":"y"}
One solution is to use a list/array:
var first_json = {"name":"joe", "age":27};
var second_json = {"name":"james", "age":32};
var jsons = new Array();
jsons.push(first_json);
jsons.push(second_json);
Result
jsons = [
{"name":"joe", "age":27},
{"name":"james", "age":32}
]
if using TypeScript, you can use the spread operator (...)
var json = {...json1,...json2}
You can use Object.assign() method. The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.[1]
var o1 = { a: 1 }, o2 = { b: 2 }, o3 = { c: 3 };
var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
okay, you can do this in one line of code. you'll need json2.js for this (you probably already have.). the two json objects here are unparsed strings.
json1 = '[{"foo":"bar"},{"bar":"foo"},{"name":"craig"}]';
json2 = '[{"foo":"baz"},{"bar":"fob"},{"name":"george"}]';
concattedjson = JSON.stringify(JSON.parse(json1).concat(JSON.parse(json2)));
Just try this, using underscore
var json1 = [{ value1: '1', value2: '2' },{ value1: '3', value2: '4' }];
var json2 = [{ value3: 'a', value4: 'b' },{ value3: 'c', value4: 'd' }];
var resultArray = [];
json1.forEach(function(obj, index){
resultArray.push(_.extend(obj, json2[index]));
});
console.log("Result Array", resultArray);
Result
var baseArrayOfJsonObjects = [{},{}];
for (var i=0; i<arrayOfJsonObjectsFromAjax.length; i++) {
baseArrayOfJsonObjects.push(arrayOfJsonObjectsFromAjax[i]);
}
I use:
let jsonFile = {};
let schemaJson = {};
schemaJson["properties"] = {};
schemaJson["properties"]["key"] = "value";
jsonFile.concat(schemaJson);
The simplest way :
const json1 = { value1: '1', value2: '2' };
const json2 = { value2: '4', value3: '3' };
const combinedData = {
json1,
json2
};
console.log(combinedData)
I dont know if you want this:
U can use this for create from arrays, all arrays need contains the same number of elments.
Example:
If you have:
let a = ["a", "b", "c"];
let b = [1, 2, 3];
Use
concatArraysLikeJson([a, b]);
The result of is:
let result = {
0 : ["a", 1],
1 : ["b", 2],
2 : ["c", 3]
};
Typescript
concatArraysLikeJson(arrays:any){
let result:any = {};
let size:number = 0;
let make:boolean = true;
if(arrays.length > 0){
size = arrays[0].length;
for(let i = 1; i < arrays.length; i++){
let array = arrays[i];
if(make){
if(array.length != size){
make = false;
}
}
}
}
if(make){
for (let o = 0; o < size; o++) {
result[o] = [];
}
for(let i = 0; i < arrays.length; i++){
const array = arrays[i];
//console.log(array);
for (let o = 0; o < size; o++) {
const element = array[o];
result[o].push(element);
}
}
return result;
}else{
return false;
}
}
Javascript:
concatArraysLikeJson(arrays){
let result = {};
let size = 0;
let make = true;
if(arrays.length > 0){
size = arrays[0].length;
for(let i = 1; i < arrays.length; i++){
let array = arrays[i];
if(make){
if(array.length != size){
make = false;
}
}
}
}
if(make){
for (let o = 0; o < size; o++) {
result[o] = [];
}
for(let i = 0; i < arrays.length; i++){
const array = arrays[i];
//console.log(array);
for (let o = 0; o < size; o++) {
const element = array[o];
result[o].push(element);
}
}
return result;
}else{
return false;
}
}
The JSON Objects and Arrays can be combined in multiple ways within a structure
I can merge json with rules using json-object-merge
import JSONObjectMerge from "json-object-merge";
const target = {
store: {
book: [
{
category: "reference",
author: "Nigel Rees",
title: "Sayings of the Century",
price: 8.95
}
],
bicycle: {
color: "red",
price: 19.95
}
}
};
const source = {
store: {
book: [
{
category: "fiction",
author: "Evelyn Waugh",
title: "Sword of Honour",
isbn: "0-679-43136-5",
price: 12.99
}
]
}
};
const merged = JSONObjectMerge(target, source, { "$.store.book": "PREPEND" });
expect(merged).toEqual({
store: {
book: [
{
// books from source are prepended to the original array
category: "fiction",
author: "Evelyn Waugh",
title: "Sword of Honour",
isbn: "0-679-43136-5",
price: 12.99
},
{
category: "reference",
author: "Nigel Rees",
title: "Sayings of the Century",
price: 8.95
}
],
bicycle: {
color: "red",
price: 19.95
}
}
});

Categories

Resources