Transform 2D array to object and use first array element as key - javascript

Imagine I have this array of arrays:
myData = [
["wantThisAsKey1",someElement1,anotherElement1],
["wantThisAsKey2",someElement2,anotherElement2]
]
I need to convert this array to an object where the first element of each array is used as the key:
myDataObject = {
"wantThisAsKey1": [someElement1,anotherElement1],
"wantThisAsKey2": [someElement2,anotherElement2],
}
How can I do this in a general way, something like myDataObject = convertToObject(myData) ?

Try this:
let myData = [
["wantThisAsKey1","someElement1","anotherElement1"],
["wantThisAsKey2","someElement2","anotherElement2"]
];
let myDataObject = convertToObject(myData);
console.log(myDataObject);
function convertToObject(data){
let res = {};
for(let i = 0; i < data.length; i++)
res[data[i][0]] = data[i].slice(1);
return res;
}

To achieve this you can combine the arrays reduce function with destructuring assignment:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
myData = [
["wantThisAsKey1", 1, 2],
["wantThisAsKey2", 2, 3]
]
const newobject = myData.reduce((acc, elem) => {
const [key, ...rest] = elem;
acc[key] = rest
return acc;
}, {})
console.log(newobject);
// Result: { wantThisAsKey1: [ 1, 2 ], wantThisAsKey2: [ 2, 3 ] }

try using reduce here. like this.
const result = myData.reduce( (result, ele) => {
const [key, ...other] = ele
result[key] = other
return result
}, {})
// output = { wantThisAsKey1: [ 'someElement1', 'anotherElement1' ], wantThisAsKey2: [ 'someElement2', 'anotherElement2' ] }

Related

How to change all value in object to an shorter object - Javascript

I want change all value in an object javascript (object in array) to an shorter object (only get 2 last number), like this:
const arr = [
{
number_1: 568,
number_2: 45462,
number_3: 9861254,
number_4: 45543321
}
]
to:
const arr = [
{
number_1: 68,
number_2: 62,
number_3: 54,
number_4: 21
}
]
Please help me, thank you!
You can do something like this
const arr = [
{
number_1: 568,
number_2: 45462,
number_3: 9861254,
number_4: 45543321
}
]
console.log(arr.map(item => {
const clone = {...item};
for(let key in clone) {
clone[key] = parseInt(clone[key].toString().slice(-2));
}
return clone;
}));
This should do the trick
const arr = [
{
number_1: 568,
number_2: 45462,
number_3: 9861254,
number_4: 45543321
}
]
const arrNew = [];
for(let i in arr){
arrNew[i] = {}
for(let key of Object.keys(arr[i])){
arrNew[i][key] = +arr[i][key].toString().slice(-2);
}
}

How to create new array with key and value with 2 arrays?

I have 2 array, one for key and other for value.
Want create new array with these arrays.
key: [01, 02, 03]
value: ["hi", "hello", "welcome"]
Output I need:
[
{"key": "1","value":"hi"},
{"key": "2","value":"hello"},
{"key": "3","value":"welcome"}
]
How to get result by this way.?
My code:
output = key.map(function(obj, index){
var myObj = {};
myObj[value[index]] = obj;
return myObj;
})
Result:
[
{"1","hi"},
{"2","hello"},
{"3","welcome"}
]
const keys = [01, 02, 03];
const values = ['hi', 'hello', 'welcome'];
const res = keys.map((key, ind) => ({ 'key': ''+key, 'value': values[ind]}));
console.log(res);
There is also a proposal for the following method of Object, fromEntries, which will do exactly what you want to, but it is not supported yet by the major browsers:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries
var myArray = [];
var keys = [45, 4, 9];
var cars = ["Saab", "Volvo", "BMW"];
cars.forEach(myFunction);
var txt=JSON.stringify(myArray);
document.getElementById("demo").innerHTML = txt;
function myFunction(value,index,array) {
var obj={ key : keys[index], value : value };
myArray.push(obj);
}
<p id="demo"></p>
You could take an object with arbitrary count of properties amd map new objects.
var key = [1, 2, 3],
value = ["hi", "hello", "welcome"],
result = Object
.entries({ key, value })
.reduce((r, [k, values]) => values.map((v, i) => Object.assign(
{},
r[i],
{ [k]: v }
)), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Here you have another apporach using reduce():
let keys = [01, 02, 03];
let values = ['hi', 'hello', 'welcome'];
let newArray = keys.reduce((res, curr, idx) => {
res.push({'key': curr.toString(), 'value': values[idx]});
return res;
}, []);
console.log(newArray);

Javascript how to join two arrays having same property value?

How do I join arrays with the same property value? I cannot map it because it has different indexes.
var array1 = [
{'label':"label1",'position':0},
{'label':"label3",'position':2},
{'label':"label2",'position':1},
];
var array2 = [
{'label':"label1",'value':"TEXT"},
{'label':"label2",'value':"SELECT"}
];
expected output:
var array3 = [
{'label':"label1",'value':"TEXT",'position':0},
{'label':"label2",'value':"SELECT", 'position':1}
];
This is what I did, I cannot make it work,
var arr3 = arr1.map(function(v, i) {
return {
"label": v.label,
"position": v.position,
"value": arr2[?].value
}
});
I think you can use array#reduce to do something like this perhaps:
var array1 = [
{'label':"label1",'position':0},
{'label':"label3",'position':2},
{'label':"label2",'position':1},
];
var array2 = [
{'label':"label1",'value':"TEXT"},
{'label':"label2",'value':"SELECT"}
];
var array3 = array2.reduce((arr, e) => {
arr.push(Object.assign({}, e, array1.find(a => a.label == e.label)))
return arr;
}, [])
console.log(array3);
You could take a Map and check the existence for a new object.
var array1 = [{ label: "label1", position: 0 }, { label: "label3", position: 2 }, { label: "label2", position: 1 }],
array2 = [{ label: "label1", value: "TEXT" }, { label: "label2", value: "SELECT" }],
map = array1.reduce((m, o) => m.set(o.label, o), new Map),
array3 = array2.reduce((r, o) => {
if (map.has(o.label)) {
r.push(Object.assign({}, o, map.get(o.label)));
}
return r;
}, []);
console.log(array3);
.as-console-wrapper { max-height: 100% !important; top: 0; }
As per the effort, we take an assumption that array1 will be having all the labels that are in array2.
Based on that first, create a map for array2and with key being labels. Post that, filter out array1 items which have labels existing in the map and then finally merging the objects of the filtered array and its corresponding values in map extracted from array2.
var array1 = [{'label':"label1",'position':0},{'label':"label3",'position':2},{'label':"label2",'position':1}];
var array2 = [{'label':"label1",'value':"TEXT"},{'label':"label2",'value':"SELECT"}];
let map = array2.reduce((a,{label, ...rest}) => Object.assign(a,{[label]:rest}),{});
let result = array1.filter(({label}) => map[label]).map(o => ({...o, ...map[o.label]}));
console.log(result);
Also, in the above snippet, you can improve the performance further by using Array.reduce against filter and map functions to retrieve the result.
var array1 = [{'label':"label1",'position':0},{'label':"label3",'position':2},{'label':"label2",'position':1}];
var array2 = [{'label':"label1",'value':"TEXT"},{'label':"label2",'value':"SELECT"}];
let map = array2.reduce((a,{label, ...rest}) => Object.assign(a,{[label]:rest}),{});
let result = array1.reduce((a,o) => {
if(map[o.label]) a.push({...o, ...map[o.label]});
return a;
}, []);
console.log(result);
If you don't know in advance which array(s) will have their labels be a subset of the other (if any), here's a method that allows for either array1 or array2 to have labels that the other array lacks. Use reduce over array1, finding the matching label in array2 if it exists:
var array1 = [
{'label':"label1",'position':0},
{'label':"label3",'position':2},
{'label':"label2",'position':1},
];
var array2 = [
{'label':"label1",'value':"TEXT"},
{'label':"label2",'value':"SELECT"}
];
const output = array1.reduce((a, { label, position }) => {
const foundValueObj = array2.find(({ label: findLabel }) => findLabel === label);
if (!foundValueObj) return a;
const { value } = foundValueObj;
a.push({ label, value, position });
return a;
}, []);
console.log(output);
See Array.prototype.map() and Map for more info.
// Input.
const A = [{'label':"label1",'position':0},{'label':"label3",'position':2},{'label':"label2",'position':1}]
const B = [{'label':"label1",'value':"TEXT"},{'label':"label2",'value':"SELECT"}]
// Merge Union.
const mergeUnion = (A, B) => {
const mapA = new Map(A.map(x => [x.label, x]))
return B.map(y => ({...mapA.get(y.label), ...y}))
}
// Output + Proof.
const output = mergeUnion(A, B)
console.log(output)
This works.
Approach: Concatenate the objects with same label, using Object.assign()
var array1 = [{'label':"label1",'position':0},{'label':"label3",'position':2},{'label':"label2",'position':1}];
var array2 = [{'label':"label1",'value':"TEXT"},{'label':"label2",'value':"SELECT"}];
var result = [];
array2.forEach(function(value, index){
result.push(Object.assign({},array1.find(function(v,i){return v.label==value.label}),value));
});
console.log(result)
Im not good with javascript,but you could also do this
var array1 = [
{'label':"label1",'position':0},
{'label':"label3",'position':2},
{'label':"label2",'position':1},
];
var array2 = [
{'label':"label1",'value':"TEXT"},
{'label':"label2",'value':"SELECT"}
];
var array3=[];
for(var i=0;i<array1.length;i++)
{
for(var x=0;x<array2.length;x++)
{
console.log(array1[i]['label'] == array2[x]['label']);
if(array1[i]['label'] == array2[x]['label']){
array3.push({label:array1[i]['label'],value:array2[x]['value'],position:array1[i]['position']});
}
}
}
console.log(array3);

lodash convert array of objects to single array of keys and multiple array of values

I need to transmit some data, that has too many key-value pairs.
As the keys are similar, I dont want to transmit them with each object.
Consider I have the following data:
[
{
x:11,
y:12
},{
x:21,
y:22
},{
x:31,
y:32
},{
x:41,
y:42
}
];
And I need the final output as
[ [x,y],[[11,12],[21,22],[31,32],[41,42]] ] OR
[ [x,y],[11,12],[21,22],[31,32],[41,42] ]
On the other end, I should be able to convert back to its original form.
It would be great if it can handle an additional key in some of the objects
I think I have seen lodash or underscore function for something close/similar to this, but I'm not able to find it right now.
NOTE: I don't know what the keys will be
Lodash v4.17.1
modify original
var modifiedOriginal = _.chain(original)
.map(_.keys)
.flatten()
.uniq()
.thru(function(header){
return _.concat(
[header],
_.map(original, function(item) {
return _.chain(item)
.defaults(_.zipObject(
header,
_.times(_.size(header), _.constant(undefined))
))
.pick(header)
.values()
.value()
})
);
})
.value();
modified back to original (keys order is not
guarantee)
var backToOriginal = _.map(_.tail(modified), function(item) {
return _.chain(_.head(modified))
.zipObject(item)
.transform(function(result, val, key) {
if (!_.isUndefined(val)) {
result[key] = val;
}
})
.value();
});
JSFiddle code https://jsfiddle.net/wa8kaL5g/1/
Using Array#reduce
var arr = [{
x: 11,
y: 12
}, {
x: 21,
y: 22
}, {
x: 31,
y: 32
}, {
x: 41,
y: 42
}];
var keys = Object.keys(arr[0]);
var op = arr.reduce(function(a, b) {
var arr = keys.reduce(function(x, y) {
return x.concat([b[y]]);
}, [])
return a.concat([arr]);
}, [keys]); //If all the objects are having identical keys!
console.log(JSON.stringify(op));
A little more verbose way of doing it:
[Edit: added the function to convert it back]
function convert(arr) {
var retArr = [ [/* keys (retArr[0]) */], [/* values (retArr[1]) */] ]
arr.forEach(function(obj){
// create new array for new sets of values
retArr[1].push([])
// put all of the keys in the correct array
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
// does the key exist in the array yet?
if (retArr[0].indexOf(key) === -1) {
retArr[0].push(key)
}
// get last index of retArr[1] and push on the values
retArr[1][retArr[1].length - 1].push(obj[key])
}
}
})
return retArr
}
function reConvert(arr) {
var retArr = []
var keys = arr[0]
arr[1].forEach(function(itemArr){
var obj = {}
itemArr.forEach(function(item, i){
obj[keys[i]] = item
})
retArr.push(obj)
})
return retArr
}
var objArr = [
{
x:11,
y:12
},{
x:21,
y:22
},{
x:31,
y:32
},{
x:41,
y:42
}
]
var arrFromObj = convert(objArr)
var objFromArr = reConvert(arrFromObj)
console.log(arrFromObj)
console.log(objFromArr)
A solution using Underscore.
First work out what the keys are:
var keys = _.chain(data)
.map(_.keys)
.flatten()
.uniq()
.value();
Then map across the data to pick out the value for each key:
var result = [
keys,
_.map(data, item => _.map(keys, key => item[key]))
];
and back again:
var thereAndBackAgain = _.map(result[1], item => _.omit(_.object(result[0], item), _.isUndefined));
Lodash's version of object is zipObject and omit using a predicate is omitBy:
var thereAndBackAgain = _.map(result[1], item => _.omitBy(_.zipObject(result[0], item), _.isUndefined));
var data = [
{
x:11,
y:12,
aa: 9
},{
x:21,
y:22
},{
x:31,
y:32,
z: 0
},{
x:41,
y:42
}
];
var keys = _.chain(data)
.map(_.keys)
.flatten()
.uniq()
.value();
var result = [
keys,
_.map(data, item => _.map(keys, key => item[key]))
];
var thereAndBackAgain = _.map(result[1], item => _.omit(_.object(result[0], item), _.isUndefined));
console.log(result)
console.log(thereAndBackAgain)
<script src="
https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
In ES6 you can do it by reducing it with Object.values(), and Object.keys(). You can restore it using a combination of Array.prototype.map() and Array.prototype.reduce():
const convertStructure = (data) => data.reduce((s, item) => {
s[1].push(Object.values(item));
return s;
}, [Object.keys(data[0]), []]); // all objects should be the same, so we can take the keys from the 1st object
const restoreStructure = ([keys, data]) => data.map((item) => item.reduce((o, v, i) => {
o[keys[i]] = v;
return o;
}, {}));
const data = [{
x: 11,
y: 12
}, {
x: 21,
y: 22
}, {
x: 31,
y: 32
}, {
x: 41,
y: 42
}];
const convertedStructure = convertStructure(data);
console.log('convertedStructure:\n', convertedStructure);
const restoredStructure = restoreStructure(convertedStructure);
console.log('restoredStructure:\n', restoredStructure);

array map, map array as a key of an array

I know the title might sounds confusing, but i'm stuck for an hour using $.each. Basically I have 2 arrays
[{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
and [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
How do I put one into another as a new property key like
[{
"section_name": "abc",
"id": 1,
"new_property_name": [{
"toy": "car"
}, {
"tool": "knife"
}]
}, {
"section_name": "xyz",
"id": 2,
"new_property_name": [{
"weapon": "cutter"
}]
}]
ES6 Solution :
const arr = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
const arr2 = [{"toy":"car","id":1},{"tool":"knife","id":1},{"weapons":"cutter","id":2}];
const res = arr.map((section,index) => {
section.new_property_name = arr2.filter(item => item.id === section.id);
return section;
});
EDIT : Like georg mentionned in the comments, the solution above is actually mutating arr, it modifies the original arr (if you log the arr after mapping it, you will see it has changed, mutated the arr and have the new_property_name). It makes the .map() useless, a simple forEach() is indeed more appropriate and save one line.
arr.forEach(section => {
section.new_property_name = arr2.filter(item => item.id === section.id));
});
try this
var data1 = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
var data2 = [{"toy":"car","id":1},{"tool":"knife","id":1},{"weapons":"cutter","id":2}];
var map = {};
//first iterate data1 the create a map of all the objects by its ids
data1.forEach( function( obj ){ map[ obj.id ] = obj });
//Iterate data2 and populate the new_property_name of all the ids
data2.forEach( function(obj){
var id = obj.id;
map[ id ].new_property_name = map[ id ].new_property_name || [];
delete obj.id;
map[ id ].new_property_name.push( obj );
});
//just get only the values from the map
var output = Object.keys(map).map(function(key){ return map[ key ] });
console.log(output);
You could use ah hash table for look up and build a new object for inserting into the new_property_name array.
var array1 = [{ "section_name": "abc", "id": 1 }, { "section_name": "xyz", "id": 2 }],
array2 = [{ "toy": "car", "section_id": 1 }, { "tool": "knife", "section_id": 1 }, { "weapons": "cutter", "section_id": 2 }],
hash = Object.create(null);
array1.forEach(function (a) {
a.new_property_name = [];
hash[a.id] = a;
});
array2.forEach(function (a) {
hash[a.section_id].new_property_name.push(Object.keys(a).reduce(function (r, k) {
if (k !== 'section_id') {
r[k] = a[k];
}
return r;
}, {}));
});
console.log(array1);
Seems like by using Jquery $.merge() Function you can achieve what you need. Then we have concat function too which can be used to merge one array with another.
Use Object.assign()
In your case you can do it like Object.assign(array1[0], array2[0]).
It's very good for combining objects, so in your case you just need to combine your objects within the array.
Example of code:
var objA = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}];
var objB = [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
var objC = Object.assign({},objA[0],objB[0]);
console.log(JSON.stringify(objC));// {"section_name":"abc","id":1,"toy":"car","section_id":1}
For more info, you can refer here: Object.assign()
var firstArray = [{"section_name":"abc","id":1},{"section_name":"xyz","id":2}],
secondArray = [{"toy":"car","section_id":1},{"tool":"knife","section_id":1},{"weapons":"cutter","section_id":2}];
var hash = Object.create(null);
firstArray.forEach(s => {
hash[s.id] = s;
s['new_property_name'] = [];
});
secondArray.forEach(i => hash[i['section_id']]['new_property_name'].push(i));
console.log(firstArray);

Categories