I have a bothersome length of characters before all keys in this object. Since they are all the same, I would like to do a .map() or forEach() or something with a .slice() in it to remove the first n characters. How is this done to all keys in the object?
I should say that we are already importing Lodash in the project so I can use that.
So I need to turn this:
{
'remove.this.string.a': "apple",
'remove.this.string.b': "banana",
'remove.this.string.c': "carrot",
'remove.this.string.d': "diakon"
}
and turn it into:
{
"a": "apple",
"b": "banana",
"c": "carrot",
"d": "diakon"
}
Use object.entries to get the keys and values. Loop over changing the key.
Changing the object directly
var obj = {
'remove.this.string.a': "apple",
'remove.this.string.b': "banana",
'remove.this.string.c': "carrot",
'remove.this.string.d': "diakon"
}
// Object.entries(obj).forEach(function(arr) {
// var key = arr[0]
// var value = arr[1]
// delete obj[key]
// obj[key.split(".").pop()] = value
// })
Object.entries(obj).forEach(([key, value]) => {
delete obj[key]
obj[key.split(".").pop()] = value
})
console.log(obj)
or reduce to create a new object
var obj = {
'remove.this.string.a': "apple",
'remove.this.string.b': "banana",
'remove.this.string.c': "carrot",
'remove.this.string.d': "diakon"
}
// const updated = Object.entries(obj).forEach(function(obj, arr) {
// var key = arr[0]
// var value = arr[1]
// obj[key.split(".").pop()] = value
// return obj
// }, {})
const updated = Object.entries(obj).reduce((obj, [key, value]) => {
obj[key.split(".").pop()] = value
return obj
}, {})
console.log(updated)
Another approach that avoinds the need for Object.fromEntries(), would be to use Array.reduce() as shown:
const input = {
'remove.this.string.a': "apple",
'remove.this.string.b': "banana",
'remove.this.string.c': "carrot",
'remove.this.string.d': "diakon"
};
const output = Object.entries(input).reduce((result, [key, value]) => {
/* Pluck last letter of key string */
const letter = key.slice(-1);
/* Insert letter key/value into result object */
return { ...result, [letter] : value };
}, {});
console.log(output);
If you've already got lodash, _.mapKeys is what you're looking for. Here's an example of what you asked for directly (to just slice to 19 characters), but you could easily do a split or replace or whatever else you'd like:
var _ = require('lodash')
let data = {
'remove.this.string.a': "apple",
'remove.this.string.b': "banana",
'remove.this.string.c': "carrot",
'remove.this.string.d': "diakon"
}
_.mapKeys(data, (val, key) => key.slice(19))
Here's a runkit:
https://runkit.com/daedalus28/slice-keys
let obj = {
'remove.this.string.a': "apple",
'remove.this.string.b': "banana",
'remove.this.string.c': "carrot",
'remove.this.string.d': "diakon"
};
let transformed = Object.entries(obj).reduce((t, [key, value]) => {
t[key.substr(19)] = value;
return t;
}, {});
console.log(transformed);
You could use the new Object.fromEntries along with Object.entries:
let remove = {
this: {
string: {}
}
}
remove.this.string.a = "apple"
remove.this.string.b = "banana"
remove.this.string.c = "carrot"
remove.this.string.d = "diakon"
console.log(remove.this.string)
let fixed = Object.fromEntries(
Object.entries(remove.this.string)
.map(([key, val]) => [key, val])
)
console.log(fixed)
Result:
{ a: 'apple', b: 'banana', c: 'carrot', d: 'diakon' }
Update:
For keys that are all one string:
let remove = {
'remove.this.string.a': 'apple',
'remove.this.string.b': 'banana',
'remove.this.string.c': 'carrot',
'remove.this.string.d': 'diakon'
}
let fixed = Object.fromEntries(
Object.entries(remove)
.map(([key, val]) => [key.replace('remove.this.string.', ''), val])
)
console.log(fixed)
Result:
{ a: 'apple', b: 'banana', c: 'carrot', d: 'diakon' }
Related
The question itself is probably in need of editing but hear me out pls. I have this:
[
["a","b","c"],
["apple", "orange", "banana"],
["kiwi", "tomato", "avocado"],
["beans", "asparagus", "spinach"]
]
I need it so that it will look like the one below:
[
{"a":"apple", "b":"orange", "c":"banana"},
{"a":"kiwi", "b":"tomato", "c":"avocado"},
{"a":"a", "b":"asparagus", "c":"spinach"}
]
I have done something like this:
const rows = [
["a","b","c"],
["apple", "orange", "banana"],
["kiwi", "tomato", "avocado"],
["beans", "asparagus", "spinach"]
]
const dataObj = {};
const dataArr = [];
if (rows.length) {
keys = rows[0];
values = rows[0];
rows.forEach((element, i) => {
values = rows[i];
keys.forEach((key, j) => {
dataObj[key] = values[j];
dataArr.push(dataObj);
});
});
}
To no avail and got something like this:
[
{"a":"apple", "b":"orange", "c":"banana"},
{"a":"apple", "b":"orange", "c":"banana"},
{"a":"apple", "b":"orange", "c":"banana"}
]
This is not the desired output. If you can help me out - and our community! - it would be super. Thanks!
You can use couple of Array functions to achieve this:
Array.shift: To pick the first element and remove it from array
Array.map: To transform items into object
const rows = [
["a", "b", "c"],
["apple", "orange", "banana"],
["kiwi", "tomato", "avocado"],
["beans", "asparagus", "spinach"]
]
const keys = rows.shift();
const map = rows.map((item) => {
const obj = {}
keys.forEach((key, index) => {
obj[key] = item[index]
})
return obj
})
console.log(map)
If you can use lodash:
Check it out in this sandbox
import _ from 'lodash';
const input = [
["a","b","c"],
["apple", "orange", "banana"],
["kiwi", "tomato", "avocado"],
["beans", "asparagus", "spinach"]
]
const keys = input[0];
const values = input.splice(1);
console.log(keys);
console.log(values);
const output = values.map(row => _.zipObject(keys, row));
console.log(output);
/*
[
{"a":"apple","b":"orange","c":"banana"},
{"a":"kiwi","b":"tomato","c":"avocado"},
{"a":"beans","b":"asparagus","c":"spinach"}
]
*/
Modified your code a little bit for the solution
const rows = [
["a","b","c"],
["apple", "orange", "banana"],
["kiwi", "tomato", "avocado"],
["beans", "asparagus", "spinach"]
]
let dataObj = {};
const dataArr = [];
if (rows.length) {
keys = rows[0];
rows.forEach((row, i) => {
if(i==0)
return
dataObj = {}
keys.forEach((key, j) => {
dataObj[key] = row[j];
});
dataArr.push(dataObj);
});
}
console.log(dataArr)
How to create array of object from two different length of array
for example
arr1 = ["first","second","third","fourth","fifth","Sixth"]
arr2 = [["1","2","3","4","5","6"],["7","8","9","10","11","12"],["1","2","3","4"]]
finalArray = [{
first:1,
second:2
third:3,
fourth:4,
fifth:5,
sixth:6
},{
first:7,
second:8
third:9,
fourth:10,
fifth:11,
sixth:12
}]
I tried this using map but getting every key value pair as whole object
example
[
{first: 1}
{second: 2}
{third: 3}
{fourth: 4}
]
With map() and reduce():
const arr1 = ["first", "second", "third", "fourth", "fifth", "Sixth"];
const arr2 = [["1", "2", "3", "4", "5", "6"],
["7", "8", "9", "10", "11", "12"],
["1", "2", "3", "4"]];
const res = arr2.map(v => v.reduce((a, v, i) => ({...a, [arr1[i]]: v}), {}));
console.log(res);
You can take advantage of Array.prototype.reduce to update the shape of the result array
let arr1 = ["first","second","third","fourth","fifth","Sixth"];
let arr2 = [["1","2","3","4","5","6"],["7","8","9","10","11","12"],["1","2","3","4"]];
let result = arr2.reduce((accumulator, current) => {
let obj = arr1.reduce((acc, currentKey, index) => {
if(current.indexOf(index) && current[index] !== undefined ){
acc[[currentKey]] = current[index];
}
return acc;
}, {});
return accumulator.concat(obj);
}, []);
console.log(result);
without reduce() and covered edge case when the arr1 contains fewer elements as the element from arr2
const arr1 = ["first","second","third","fourth","fifth","Sixth"]
const arr2 = [["1","2","3","4","5","6"],["7","8","9","10","11","12"],["1","2","3","4"]]
const res = arr2.map(values => {
const res = {}
for(const [index, value] of arr1.entries()){
if(values[index]) {
res[value] = values[index] // or parseInt(values[index])
} else {
break
}
}
return res
})
console.dir(res)
var c = {
'aa-bb': [{ a: 1, v: 2}],
'cc-xz': [{ c: 2}]
}
console.log(Object.keys(c))
I need to create an object, whose keys (the name) must be from Object.keys.
For each key name an object of type array must be defined as below.
Can you give me a hand?
result:
const res = {
'aa-bb': Array(number).fill(0),
'cc-xz': Array(number).fill(0)
};
var c = {
'aa-bb': [{
a: 1,
v: 2
}],
'cc-xz': [{
c: 2
}]
}
const keys = Object.keys(c);
let res = {},
number = 5;
keys.forEach(key => res[key] = Array(number).fill(0));
console.log(res);
Map the keys, and create pairs of [key, array], and convert back to an object using Object.fromEntries():
const fn = (obj, arrLengh) =>
Object.fromEntries(
Object.keys(obj)
.map(key => [key, Array(arrLengh).fill(0)])
);
const c = {"aa-bb":[{"a":1,"v":2}],"cc-xz":[{"c":2}]};
const result = fn(c, 5);
console.log(result);
Suppose i have an array:
const items = [
{
"amount1": "100",
"amount2": "50",
"name": "ruud"
},
{
"amount1": "40",
"amount2": "60",
"name": "ted"
}
]
I want to get all amount1 and amount2 props totalled and result in:
[
{
"amount1": 140,
"amount2": 110
}
]
How can I do this?
Using Array.prototype.reduce() with Object.entries() and Array.prototype.forEach():
const items = [{amount1: 100, amount2: 50}, {amount1: 40, amount2: 60}];
const sums = items.reduce((acc, item) => {
Object.entries(item).forEach(([k, v]) => acc[k] = (acc[k] || 0) + v);
return acc;
}, {});
console.log(sums);
To filter out non-number properties (but keep quoted number strings, as per the updated question):
const items = [{amount1: '100', amount2: '50', name: 'Ruud'}, {amount1: '40', amount2: '60', name: 'Ted'}];
const sums = items.reduce((acc, item) => {
Object.entries(item)
.filter(([_, v]) => !isNaN(v))
.forEach(([k, v]) => acc[k] = (acc[k] || 0) + Number(v));
return acc;
}, {});
console.log(sums);
const items = [{amount1: 100, amount2: 50}, {amount1: 40, amount2: 60}];
function sum(data){
const keys = Object.keys(data[0])
let res = {}
for(key of keys)
res[key]=data.map(x=>x[key]).reduce((a,b)=>a+b);
return res
}
console.log(sum(items))
Here is an alternative, simple, and clean solution for this.
const items = [{amount1:100, amount2:50, name:"ruud"},{amount1:40,amount2:60,name:"ted"}]
let result = [{amount1:0,amount2:0}]
items.forEach(i=>{
result[0].amount1 += i.amount1
result[0].amount2 += i.amount2
})
console.log(result)
Above solutions are great. I included this if you don't want to use
Array.prototype.reduce(). This will work even if you have other properties which are not "numbers"
const items = [{amount1: 100, amount2: 50, name: 'Ruud'}, {amount1: 40, amount2: 60, name: 'Ted'}];
var result = {};
items.forEach(function(eachItem){
for(var prop in eachItem){
if(typeof eachItem[prop] === "number"){
result[prop] = result[prop] ? result[prop] + eachItem[prop] : eachItem[prop];
}
}
});
result = [result];
console.log(result);
You can use reduce().
Use the reduce() method on the array items
Set the accumulator(ac) as an empty object i.e {}
During each iteration through the objects create a for..in loop to iterate through all keys of object.
Check if the typeof value of key is "number" then add it otherwise don't
const items = [{amount1:100, amount2:50, name:"ruud"}, {amount1:40,amount2:60,name:"ted"}]
let res = [items.reduce((ac,x) => {
for(let key in x){
if(typeof x[key] === "number"){
if(!ac[key]) ac[key] = 0;
ac[key] += x[key]
}
}
return ac;
},{})]
console.log(res)
reduce() is indeed the way to go, but the cleanest to go only through a set of known keys is probably to pass your expected result as the accumulator and to iterate over this accumulator's keys:
const items = [
{ amount1: "100", amount2: "50", name: "ruud", foo: "unrelated" },
{ amount1: "40", amount2: "60", name: "ted", foo: "0" }
];
const result = items.reduce((acc, item) => {
for (let key in acc) { // iterate over the accumulator's keys
acc[key] += isNaN(item[key]) ? 0 : +item[key];
}
return acc;
}, { // here we define the expected format
amount1: 0,
amount2: 0
});
console.log(result);
I have following object.
var obj = [{
Address1: "dd",
Address2: "qww",
BankAccNo: "44",
BankBranchCode: "44",
BloodGrp: "A+"
},
{
Address1: "dd",
Address2: "qww",
BankAccNo: "44",
BankBranchCode: "44",
BloodGrp: "A+"
}];
How can I make all of the keys uppercase?
I want to be able to access values like this : - obj[0].ADDRESS1
obj = obj.map( function( item ){
for(var key in item){
var upper = key.toUpperCase();
// check if it already wasn't uppercase
if( upper !== key ){
item[ upper ] = item[key];
delete item[key];
}
}
return item;
});
http://jsfiddle.net/07xortqy/
Loop over all the properties in the object (with for in)
Use .toUpperCase() to get the uppercase version of the property name
Copy the value from the original property to the uppercase version
delete the original property
For anyone looking for a solution working with objects, arrays, and nested objects or arrays:
// rename function depending on your needs
const capitalizeKeys = (obj) => {
const isObject = o => Object.prototype.toString.apply(o) === '[object Object]'
const isArray = o => Object.prototype.toString.apply(o) === '[object Array]'
let transformedObj = isArray(obj) ? [] : {}
for (let key in obj) {
// replace the following with any transform function
const transformedKey = key.replace(/^\w/, (c, _) => c.toUpperCase())
if (isObject(obj[key]) || isArray(obj[key])) {
transformedObj[transformedKey] = capitalizeKeys(obj[key])
} else {
transformedObj[transformedKey] = obj[key]
}
}
return transformedObj
}
const t = {
test1: 'hello',
test2: {
aa: 0,
bb: '1',
cc: [ 3, '4', 'world']
},
test3: [{
aa: 5,
bb: '6'
}, {
cc: [ 'hello', 'world', 7 ]
}
]
}
console.log(JSON.stringify(capitalizeKeys(t)))
(this function is to be adapted since I only had to capitalize the first letter, and there is no need for the helper functions to be nested)
$.each(obj, function(i, parent) {
$.each(parent, function(key, record) {
parent[ key.toUpperCase() ] = record[key]; //rename key
delete parent[key]; //delete old key
});
});
let obj = [
{ Address1: "dd",Address2: 'qww',BankAccNo: 44,BankBranchCode: 44,BloodGrp: 'A+' },
{ Address1: "dd",Address2: 'qww',BankAccNo: 44,BankBranchCode: 44,BloodGrp: 'A+' }
];
const uppercaseKeys = (elem) => {
let newObject = {}
Object.keys(elem).reduce( (acc, key, allKeys) => {
acc[key.toUpperCase()] = elem[key]
delete elem[key]
return acc
}, elem)
return newObject
}
obj.forEach( o => uppercaseKeys )
console.log(obj)
You can now also use Object.fromEntries() in combination with Object.entries() - have a look at the Object transformations section.
const obj2 = obj1.map(item => Object.fromEntries(Object.entries(item).map(([key, val]) => [
key.toUpperCase(),
val
])));
I've detailed the steps below:
// Iterate through each item in array
const obj2 = obj1.map(item => {
// Object.entries() method returns array of object's own enumerable string-keyed property [key, value] pairs,
// in the same order as that provided by a for...in loop
const entries = Object.entries(item);
// Convert keys to uppercase
const uppercaseEntries = entries.map(([key, val]) => [
key.toUpperCase(),
val
]);
// Object.fromEntries() method transforms a list of key-value pairs into an object.
return Object.fromEntries(uppercaseEntries);
});`
https://jsfiddle.net/buj5y32x/3/
For wider support, you are better off using Object.keys() with Array.reduce().
const obj2 = obj1.map(item =>
Object.keys(item).reduce((accumulator, key) => {
// accumulator is the new object we are creating
accumulator[key.toUpperCase()] = item[key];
return accumulator;
}, {})
);
https://jsfiddle.net/qf81ezsy/
You could just loop through them and add new entries?
for (index in obj) {
for (key in obj[index]) {
obj[index][key.toUpperCase()] = obj[key];
}
}