Convert array of strings into an array of objects - javascript

I have this JavaScript array:
[ "124857202", "500255104", "78573M104" ]
I want to convert this particular array into an array of objects as shown below:
[
{ name: "124857202" },
{ name: "500255104" },
{ name: "78573M104" }
]

Use Array#map to convert each value into a different value:
var newArr = arr.map(function(value) {
return {name: value};
});
Array#map applies the callback to each element in the array and returns a new array containing the return values of the callback.

I would take a look at the array.map function in javascript.
const mappedArr = arr.map(value => {
return {
name: value
}
})

I want to convert this particular array into an array of objects as
shown below
If you want to change the actual array in place (rather than creating a new array), you can use a for loop to iterate the indexes of your array. For each index, you can replace the value with an object {name: arr[i]}. This object has a name key, and takes a value which is the current element arr[i].
const arr = [ "124857202", "500255104", "78573M104" ];
for(let i = 0; i < arr.length; i++) {
arr[i] = {name: arr[i]};
}
console.log(arr);
Or, if you want to make a new array and leave the original untouched, you can use Felix's answer, here it can be re-written to use more modern ES6 features to make it more concise, such as an arrow function and shorthand property names:
const arr = [ "124857202", "500255104", "78573M104" ];
const res = arr.map(name => ({name}));
console.log(res);

Another approach - Array#reduce.
var arr = ["124857202", "500255104", "78573M104"];
var res = arr.reduce(function(s, a){
s.push({name: a});
return s;
}, [])
console.log(res);

You can use
var arrayOfStrings = ["124857202", "500255104", "78573M104"];
var arrayOfObjects = [];
arrayOfStrings.forEach(function (element, index) {
arrayOfObjects.push({
name: element,
})
});

Felix Kling' answer, gehsekky's answer and the second part of Nick Parsons' answer are the most correct. For completeness, here is a version that uses Underscore's _.map:
import { map } from 'underscore';
var result = map(array, name => ({name}));
For this particular use case, _.map doesn't buy you much compared to Array.prototype.map except for a little bit of added portability. Going the other way, however, is a bit easier on the brain with _.map because of Underscore's iteratee shorthands:
// Underscore map
var array = map(result, 'name');
// Array.prototype.map
var array = result.map(obj => obj.name);
Underscore's map and other collection functions really shine when you need to iterate over a plain object, since JavaScript's built-in methods don't support this at all:
var objectOfStrings = {
first: "124857202",
second: "500255104",
third: "78573M104"
};
// to array of strings, Underscore
var arrayOfStrings = map(objectOfStrings);
// to array of strings, vanilla JS
var arrayOfStrings = [], value;
for (key in objectOfStrings) {
arrayOfStrings.push(objectOfStrings[key]);
}
// to array of objects, Underscore
var arrayOfObjects = map(objectOfStrings, name => ({name}));
// to array of objects, vanilla JS
var arrayOfStrings = [], name;
for (key in objectOfStrings) {
name = objectOfStrings[key];
arrayOfStrings.push({name});
}
var objectOfObjects = {
first: {name: "124857202"},
second: {name: "500255104"},
third: {name: "78573M104"}
};
// to array of strings, Underscore
var arrayOfStrings = map(objectOfStrings, 'name');
// to array of strings, vanilla JS
var arrayOfStrings = [], value;
for (key in objectOfObjects) {
arrayOfStrings.push(objectOfObjects[key].name);
}
// to array of objects, Underscore
var arrayOfObjects = map(objectOfObjects);
// to array of objects, vanilla JS
var arrayOfObjects = [], value;
for (key in objectOfStrings) {
arrayOfObjects.push(objectOfStrings[key]);
}

Related

Inserting Elements In Array As an Object but without using keys in Javascript

Current Situation :
[{
"Severity":1,
"Name":"Yash"
}, {
"Severity":2,
"Name":"Yashaswi"
}]
Desired Situation :
[{1: "Yash"}, {2: "Yashaswi"}]
Code being used :
widTags = ["Severity","Name"];
let tempobj = {};
for(let key in widTags) {
tempobj[key]=prop;
}
dataArrayWid.push(tempobj)
This solution does what you're suggesting without changing the syntax too much from your original code:
const original = [
{"Severity":1, "Name":"Yash"},
{"Severity":2, "Name":"Yashaswi"}
];
const final = [];
for (const oldObj of original){ // (Prefer `for...of` to iterate Arrays)
const
newObj = {},
key = oldObj["Severity"],
val = oldObj["Name"];
newObj[key] = val; // Uses Severity val as prop name & Name val as prop val
final.push(newObj);
}
console.log(final);
And this is a more concise version:
const
original = [ {"Severity":1, "Name":"Yash"}, {"Severity":2, "Name":"Yashaswi"} ],
final = original.map(obj => ( { [obj.Severity]: obj.Name } ));
console.log(final);
(Here, the .map method of Arrays makes a new Array with each element modified by a function -- in this case an Arrow function).
Note:
The extra parentheses tell JavaScript that their contents are an expression containing our Object literal to be returned, not a block of code statements.
Similarly, the extra brackets in the Object literal tell JavaScript that their contents are an expression specifying a computed property name, not a static property name,
You can achieve that by using Array.map() method.
Demo :
const dataArrayWid = [{
"Severity":1,
"Name":"Yash"
}, {
"Severity":2,
"Name":"Yashaswi"
}];
const result = dataArrayWid.map((obj) => {
return {
[obj.Severity]: obj.Name
}
});
console.log(result);

Combine 2 JSON objects of unequal size with ID

Problem
I would like to have the below two JSON combined together using the ID and have the expected result as mentioned below. I have tried a few solutions that were available but none worked for my use case. Any suggestions will be great !!
Tried to do:
How to merge two json object values by id with plain Javascript (ES6)
Code
var json1 = [
{
"id":"A123",
"cost":"5020.67",
"fruitName":"grapes"
},
{
"id":"A456",
"cost":"341.30",
"fruitName":"apple"
},
{
"id":"A789",
"cost":"3423.04",
"fruitName":"banana"
}
];
var json2 = [
{
"id":"A123",
"quantity":"7"
},
{
"id":"A789",
"quantity":"10"
},
{
"id":"ABCD",
"quantity":"22"
}
];
Below is the code I tried:
var finalResult = [...[json1, json2].reduce((m, a) => (a.forEach(o => m.has(o.id) && Object.assign(m.get(o.id), o) || m.set(o.id, o)), m), new Map).values()];
Expected result:
[
{
"id":"A123",
"cost":"5020.67",
"fruitName":"grapes",
"quantity":"7"
},
{
"id":"A456",
"cost":"341.30",
"fruitName":"apple"
},
{
"id":"A789",
"cost":"3423.04",
"fruitName":"banana",
"quantity":"10"
},
{
"id":"ABCD",
"quantity":"22"
}
]
You can accomplish this fairly easily without getting too fancy. Here's the algorithm:
Put the items from json1 into an object by id, so that you can look them up quickly.
For each item in json2: If it already exists, merge it with the existing item. Else, add it to objectsById.
Convert objectsById back to an array. I've used Object.values, but you can also do this easily with a loop.
var json1 = [
{
"id":"A123",
"cost":"5020.67",
"fruitName":"grapes"
}, {
"id":"A456",
"cost":"341.30",
"fruitName":"apple"
}, {
"id":"A789",
"cost":"3423.04",
"fruitName":"banana"
}
];
var json2 = [
{
"id":"A123",
"quantity":"7"
}, {
"id":"A789",
"quantity":"10"
}
];
const objectsById = {};
// Store json1 objects by id.
for (const obj1 of json1) {
objectsById[obj1.id] = obj1;
}
for (const obj2 of json2) {
const id = obj2.id;
if (objectsById[id]) {
// Object already exists, need to merge.
// Using lodash's merge because it works for deep properties, unlike object.assign.
objectsById[id] = _.merge(objectsById[id], obj2)
} else {
// Object doesn't exist in merged, add it.
objectsById[id] = obj2;
}
}
// All objects have been merged or added. Convert our map to an array.
const mergedArray = Object.values(objectsById);
I think a few steps are being skipped in your reduce function. And it was a little difficult to read because so many steps are being combined in one.
One critical piece that your function does not account for is that when you add 2 numerical strings together, it concats the strings.
const stringTotal = "5020.67" + "3423.04" // result will be "5020.673423.04"
The following functions should give you the result you are looking for.
// calculating the total cost
// default values handles cases where there is no obj in array 2 with the same id as the obj compared in array1
const calcualteStringTotal = (value1 = 0, value2 = 0) => {
const total = parseFloat(value1) + parseFloat(value2)
return `${total}`
}
const calculateTotalById = (array1, array2) => {
const result = []
// looping through initial array
array1.forEach(outterJSON => {
// placeholder json obj - helpful in case we have multiple json in array2 with the same id
let combinedJSON = outterJSON;
// looping through second array
array2.forEach(innerJSON => {
// checking ids
if(innerJSON.id === combinedJSON.id) {
// calls our helper function to calculate cost
const updatedCost = calcualteStringTotal(innerJSON.cost, outterJSON.cost)
// updating other properties
combinedJSON = {
...outterJSON,
...innerJSON,
cost: updatedCost
}
}
})
result.push(combinedJSON)
})
return result
}
const combinedResult = calculateTotalById(json1, json2)
I figured that by using reduce I could make it work.
var finalResult = [...[json1, json2].reduce((m, a) => (a.forEach(o => m.has(o.id) && Object.assign(m.get(o.id), o) || m.set(o.id, o)), m), new Map).values()];

Convert JSON to Array of Objects using lodash

I have a JSON object in NoSql database in this format. We are getting this data after migrating some records from some other database and these are multi-valued fields.(Basically we are trying to clean the data for further processing).
{
"BPContName":"aName;bName;cName",
"BPContEmail":"aEmail;bEmail;cEmail",
"BPContPWID":"aPWID;bPWID;cPWID"
}
I want to add another key "bpTableDataName" in the same JSON which should have this format and values,
"bpTableDataName": [
{
"name": "aName",
"email": "aEmail",
"pwdid": "aPWID"
},
{
"name": "bName",
"email": "bEmail",
"pwdid": "bPWID"
},
{
"name": "cName",
"email": "cEmail",
"pwdid": "cPWID"
}
],
Is there a way we can achieve this using lodash?
Try following code -
o = {
"BPContName": "aName;bName;cName",
"BPContEmail": "aEmail;bEmail;cEmail",
"BPContPWID": "aPWID;bPWID;cPWID"
}
map = { "BPContName" : "name", "BPContEmail": "email", "BPContPWID": "pwdid" }
const result = _.reduce(o, (arr, v, k) => ( v.split(";").forEach((x,i) => _.set(arr, `${i}.${map[k]}`, x)), arr ), [])
console.log(result)
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.11/lodash.min.js"></script>
You can use split() to split the values into an array.
Then iterate over the array and create the require json and then push that into results.
Check this out.
var data = {
"BPContName":"aName;bName;cName",
"BPContEmail":"aEmail;bEmail;cEmail",
"BPContPWID":"aPWID;bPWID;cPWID"
}
var names = data.BPContName.split(';');
var emails = data.BPContEmail.split(';');
var pwids = data.BPContPWID.split(';');
var results = [];
for(var i = 0 ; i < names.length; i++) {
var obj = {
name: names[i],
email: emails[i],
pwdid: pwids[i]
}
results.push(obj);
}
console.log(results)
You could reduce the entries returned by Object.entries like this:
let obj = {
"BPContName": "aName;bName;cName",
"BPContEmail": "aEmail;bEmail;cEmail",
"BPContPWID": "aPWID;bPWID;cPWID"
}
let bpTableDataName = Object.entries(obj).reduce((r, [key, value]) => {
let splits = value.split(";");
key = key.replace("BPCont", "").toLowerCase();
splits.forEach((split, i) => (r[i] = r[i] || {})[key] = split)
return r;
}, [])
obj.bpTableDataName = bpTableDataName;
console.log(obj)
Object.entries returns an array of key-value pair. Loop through each of them
split the each value at ;
get the key by removing BPCont part and making it lowerCase
Loop through the splits and update specific keys of objects at each index
Update:
Since you have an extra d in the output's key, you can create a mapping object:
propertyMap = {
"BPContName": "name",
"BPContEmail": "email",
"BPContPWID": "pwdid"
}
And inside the reduce, change the replace code to this:
key = propertyMap[key]
Using Object.assign, Object.entries, Array#map and the spread operator make this trivial
const inputdata = {
"BPContName":"aName;bName;cName",
"BPContEmail":"aEmail;bEmail;cEmail",
"BPContPWID":"aPWID;bPWID;cPWID"
};
const t1=Object.assign({},...Object.entries(inputdata).map(([k,v])=>({[k]:v.split(';')})));
inputdata.bpTableDataName=t1.BPContName.map((name,i)=>({name,email:t1.BPContEmail[i],pwdid:t1.BPContPWID[i]}));
console.log(inputdata);
Of course, it wouldn't be me without a one-liner
const obj = {
"BPContName":"aName;bName;cName",
"BPContEmail":"aEmail;bEmail;cEmail",
"BPContPWID":"aPWID;bPWID;cPWID"
};
// one line to rule them all
obj.bpTableDataName=Object.entries(obj).reduce((r,[k,v])=>(v.split(';').forEach((v,i)=>(r[i]=r[i]||{})[{BPContName:'name',BPContEmail:'email',BPContPWID:'pwdid'}[k]]=v),r),[]);
//
console.log(obj);
Basically what you need is to zip it.
Snippet:
let obj = {"BPContName":"aName;bName;cName","BPContEmail":"aEmail;bEmail;cEmail","BPContPWID":"aPWID;bPWID;cPWID"},
res = _.zipWith(
..._.map(obj, v => v.split(';')),
(name, email, pwid) => ({name, email, pwid})
);
console.log(res)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Note, the sequence of the parameters we have to put such a way, the original object give us values when using Object.values or giving us keys when using Object.keys usually it is alphabetical order. But, In case in any env the order is not guranted we can sort it with a sequence of keys as a metadata.
Or else you can explicitly pass the arguments like:
(obj.BPContName.split(';'), obj.BPContEmail.split(';'), obj.BPContPWID.split(';'))
You can use lodash's _.flow() to create a function. Use _.map() with _.overArgs() to create a function that splits the values, format the key, and then converts them to an array of pairs using _.unzip(), for example [['name', 'x'], ['name', 'y']]. Transpose the array of arrays with _.unzip() to combine pairs of different properties. Then use _.map() to iterate, and convert each array of pairs to an object using _.fromPairs().
const { flow, partialRight: pr, map, unzip, overArgs, times, size, constant, split, fromPairs } = _
const keysMap = new Map([['BPContName', 'name'], ['BPContEmail', 'email'], ['BPContPWID', 'pwdid']])
const formatKey = key => keysMap.get(key)
const splitVals = pr(split, ';')
const fn = flow(
pr(map, overArgs(
(vals, k) => unzip([vals, times(size(vals), constant(k))]),
[splitVals, formatKey])
),
unzip, // transpose
pr(map, fromPairs) // convert each pairs array to object
)
const data = {
"BPContName":"aName;bName;cName",
"BPContEmail":"aEmail;bEmail;cEmail",
"BPContPWID":"aPWID;bPWID;cPWID"
}
const results = fn(data)
console.log(results)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

Lodash: Extract property, split array, get unique values

In my JS project, I am using Lodash library to Extract property, split array, get unique values.
var taskobj = [
{'taskno':'a', 'team':'1,2'},
{'taskno':'b', 'team':'3,4'},
{'taskno':'c', 'team':'2,4'},
];
//Looping through the object to convert string to array
_.forEach(taskobj, function(value, key) {
taskobj[key].team = _.split(taskobj[key].team,',');
});
// using _.map to extract team and return array
// using _.flatten to flatten array
// using _.uniq to get unique values from flattned array.
return _.uniq(_.flatten(_.map(taskobj,'team')));
// logs - [1,2,3,4]
Is this the most efficient way to achieve this?
you can use reduce and start with a new Set() and add the values of team every time ( then convert it back to an array with the spread operator )
var taskobj = [
{'taskno':'a', 'team':'1,2'},
{'taskno':'b', 'team':'3,4'},
{'taskno':'c', 'team':'2,4'},
];
var result = [...taskobj.reduce((acc, {team}) => {
team.split(',').forEach(e => acc.add(e))
return acc
}, new Set())]
console.log(result)
This can be achieved by using lodash#flatMap with an iteratee that splits the team string into an array, which is then flattened by the mentioned function and then use lodash#uniq to get the final result.
var result = _.uniq(_.flatMap(taskobj, ({ team }) => team.split(',')));
var taskobj = [
{'taskno':'a', 'team':'1,2'},
{'taskno':'b', 'team':'3,4'},
{'taskno':'c', 'team':'2,4'},
];
var result = _.uniq(_.flatMap(taskobj, ({ team }) => team.split(',')));
console.log(result);
.as-console-wrapper{min-height:100%;top:0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Use simpler version
try this
var teams = [];
var taskobj = [
{'taskno':'a', 'team':'1,2'},
{'taskno':'b', 'team':'3,4'},
{'taskno':'c', 'team':'2,4'},
];
taskobj.map(obj => {
var teamSplit = obj.team.split(',');
teams = [...teams, ...teamSplit];
})
var uniqTeams = _.uniq(teams);
console.log('teams', teams);
console.log('uniqTeams', uniqTeams)
JsBin link
http://jsbin.com/bedawatira/edit?js,console

Underscore: How to return all values by array with keys

I have big object with a lot of key : value, and I have array with some keys from this object.
How to return values of this keys(array) by underscore?
I try some like this, but it's bull**
_.find(objectwithkeysandvalues , function(value){
return _.intersection(value,arraywithekeys)
});
You don't need Underscore for this task. Instead, you can use the map function to create a new array that contains the values specified by the keys in the old array:
var myValues = keys.map(function (key) {
return myObject[key]
});
You only need to map each value from your keys array to yourBigObject[value].
In Underscore this would look like this :
var keys = [ ... ]; // Keys from your big object
var obj = { ... }; // Your big object
var values = _.map(keys, function(value, index) {
return obj[value];
});
See this fiddle for experimenting.
Here's a solution using upcoming EcmaScript 7 Array Comprehensions available today via Babel.js.
Try it: Array Comprehensions Example.
ES7:
var obj = {
"key1": 1,
"key2": 2,
"key3": 3
}
var arr = ["key1"];
var values = [for(key of arr) obj[key]];
console.log(values);

Categories