Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I am trying to replace name, occupation and title for the following array of objects and capitalise each value. Some of the values can be null and if the value is null then replace null with "N/A". What would be the shortest/best way in es6 without all the if/else statements?
const array = [{
"id": 1,
"name": "sarah",
"title": "miss,
"occupation": "student"
}, {
"id": 2,
"name": null,
"title" : null,
"occupation": null,
}]
What I have so far:
const result = array.map((x) => {
if (x.name){
x.name = x.name.charAt(0).toUpperCase() + x.name.slice(1)
} else {
x.name = "N/A"
}
if (x.title){
x.title = x.title.charAt(0).toUpperCase() + x.title.slice(1)
} else {
x.title = "N/A"
}
if (x.occupation){
x.occupation = x.occupation.charAt(0).toUpperCase() + x.occupation.slice(1)
} else {
x.occupation = "N/A"
}
return x
});
Expected output:
const array = [{
"id": 1,
"name": "Sarah",
"title": "Miss,
"occupation": "Student"
}, {
"id": 2,
"name": "N/A",
"title" : "N/A",
"occupation": "N/A",
}]
You can just create a function which does the repetitive work
const array = [{
"id": 1,
"name": "sarah",
"title": "miss",
"occupation": "student"
}, {
"id": 2,
"name": null,
"title": null,
"occupation": null,
}]
function assignValue(a) {
return a ? a.charAt(0).toUpperCase() + a.slice(1) : "N/A"
}
const newData = array.map(a => {
return {
id: a.id,
name: assignValue(a.name),
title: assignValue(a.title),
occupation: assignValue(a.occupation)
}
});
console.log(newData)
const output = array.map(object => {
return Object.fromEntries(Object.entries(object).map(entry => {
if(entry[0] == "id") return [entry[0], entry[1]]
const newValue = entry[1] ? entry[1].charAt(0).toUpperCase() + entry[1].slice(1) : "N/A"
return [entry[0], newValue]
}));
});
This uses ES8 features.
You can make it more generic for any string value as part of your object definition
const array = [{
id: 1,
name: "first middle last",
title: "miss",
occupation: "software engineer"
},
{
id: 2,
name: null,
title: null,
occupation: "student"
}
];
capitalize = (str) => {
return str
.toLowerCase()
.split(" ")
.map((wrd) => {
return wrd[0].toUpperCase() + wrd.slice(1);
})
.join(" ");
};
const transformArr = array.map((el) => {
for (const key of Object.keys(el)) {
if (!el[key]) {
el[key] = "N/A";
} else if (typeof el[key] === "string") {
el[key] = capitalize(el[key]);
}
}
return el;
});
console.log(transformArr);
You can use a small little function to avoid all the duplicate code:
function leadingUpper(str) {
if (str) {
return str.charAt(0).toUpperCase() + str.slice(1);
} else {
return "N/A";
}
}
Then, if you can modify the array in place, you won't need to create a new duplicate array:
for (const obj of array) {
for (const field of ["name", "title", "occupation"]) {
array[field] = leadingUpper(array[field]);
}
}
Or, if you want to create the new array, rather than modifying the existing one:
const result = array.map(obj => {
for (const field of ["name", "title", "occupation"]) {
array[field] = leadingUpper(array[field]);
}
});
Or, you could even embed the leadingUpper() function inline if you want:
const result = array.map(obj => {
for (const field of ["name", "title", "occupation"]) {
const str = array[field];
array[field] = str ? str.charAt(0).toUpperCase() + str.slice(1) : "N/A";
}
});
Note: Unlike some of the other solutions offered, this is "safe" in that it only modifies the specifically named properties name, title and occupation. If there happen to be other properties on any of the objects, it won't modify them. I consider this a good, defensive coding practice that isn't brittle if some other developer adds a new property to the object in the future that isn't supposed to get the capitalization treatment.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I want to create expectedObj from currentObj to be sent as response to the API. How can I do it?
The "value" and "label" will always have same values.
These are fixed set of keys. ignore_whitespace is not needed in expectedObj. No other keys are required to be removed.
let currentObj = {
"partnerId": "1",
"platform": {
"label": "ADP",
"value": "ADP"
},
"subPlatform": {
"value": "Health",
"label": "Health"
},
"activeIndicator": {
"value": "Inactive",
"label": "Inactive"
},
"partnerNotes": "",
"ignore_whitespace": false
}
let expectedObj={
"partnerId": "1",
"platform": "ADP",
"subPlatform": Health,
"activeIndicator": "Inactive",
"partnerNotes": ""
}
What I have tried is this
for let (item in currentObj) {
something
}
This will do the transforms you need (as discussed in the comments, no more keys are expected, values are always the same as labels, etc):
let currentObj = {
"partnerId": "1",
"platform": {
"label": "ADP",
"value": "ADP"
},
"subPlatform": {
"value": "Health",
"label": "Health"
},
"activeIndicator": {
"value": "Inactive",
"label": "Inactive"
},
"partnerNotes": "",
"ignore_whitespace": false
}
let expected = {
...currentObj,
platform: currentObj.platform.value,
subPlatform: currentObj.subPlatform.value,
activeIndicator: currentObj.activeIndicator.value,
}
delete expected.ignore_whitespace;
console.log(expected);
Something like this should do what you're looking for:
const expectedObj = Object.entries(currentObj).reduce((a, [k, v]) => {
if (v?.value !== undefined) a[k] = v.value;
else a[k] = v;
return a;
}, {});
Expand this code snippet for a working example:
const currentObj = {
partnerId: '1',
platform: {
label: 'ADP',
value: 'ADP',
},
subPlatform: {
value: 'Health',
label: 'Health',
},
activeIndicator: {
value: 'Inactive',
label: 'Inactive',
},
partnerNotes: '',
ignore_whitespace: false,
};
const expectedObj = Object.entries(currentObj).reduce((a, [k, v]) => {
if (v?.value !== undefined) a[k] = v.value;
else a[k] = v;
return a;
}, {});
console.log(expectedObj);
I have the array of objects as below. I want to loop through it and get Closed property values. It should be a concatenation of all the values found in each object.
For e.g. in below case, i want final result as 121212 since it has 12 in all the 3 objects.
const data = [
{
"personId": "1208007855",
"details": {
"Closed": "12"
}
},
{
"personId": "1559363884",
"details": {
"Closed": "12"
}
},
{
"personId": "973567318",
"details": {
"Closed": "12"
}
}
]
can someone let me know how to achieve this. I tried this way but couldnt succeed in achieving the result. I could only get the value of first object. Not sure how i can concatenate and store next values in this loop
There might be a situation where some objects might not have Closed property.
const totalClosed = data.forEach(function (arrayItem) {
const x = arrayItem.details.Closed;
console.log(x);
});
Try the following:
const data = [
{
"personId": "1208007855",
"details": {
"Closed": "12"
}
},
{
"personId": "1559363884",
"details": {
"Closed": "12"
}
},
{
"personId": "973567318",
"details": {
"Closed": "12"
}
}
];
result = '';
for (let i in data) {
result += data[i].details.Closed
}
You can use the .reduce function:
data.reduce((accumulator, item) => accumulator += item.details.Closed, '')
=> 121212
Using foreach exactly the same way you were trying:
const data = [
{
personId: '1208007855',
details: {
Closed: '12'
}
},
{
personId: '1559363884',
details: {
Closed: '12'
}
},
{
personId: '973567318',
details: {
Closed: '12'
}
}
];
let totalClosed = '';
data.forEach(function (arrayItem) {
totalClosed = totalClosed + arrayItem.details.Closed;
});
console.log(totalClosed);
In functional way, using reduce
const data = [
{
"personId": "1208007855",
"details": {
"Closed": "12",
"Analyze": "10"
}
},
{
"personId": "1559363884",
"details": {
"Closed": "12",
"Analyze": "10"
}
},
{
"personId": "973567318",
"details": {
"Closed": "12",
"Analyze": "10"
}
}
]
const { Closed, Analyze } = data.reduce((acc, cur) => {
acc.Closed += cur?.details?.Closed ?? ''
acc.Analyze += cur?.details?.Analyze ?? ''
return acc
}, { Closed: "", Analyze: "" })
console.log({ Closed, Analyze })
let str = "";
for(let i=0; i<data.length;i++){
str+= data[i].details.Closed;
}
console.log(str);
Also, with forEach, the elements might not be processed in the same order (0 to n) and you may find different results than you expect.
If you want a string and have an array, the best method is reduce:
const totalClosed = data.reduce(function (accumulator, currentVal) {
const closed = currentVal.details.Closed || '';
return accumulator + closed;
}, '');
let str = ''
const totalClosed = data.forEach(function (arrayItem) {
if(arrayItem.details.Closed){
str += arrayItem.details.Closed;
}
});
console.log(str)
You can create an empty string and add to it if the closed field exists, if there is another condition in 'Closed' you can check there in the if statement.
You can reduce the data entries by destructuring the entry in the reducer and concatenating the Closed value to the running res (result). You can use the nullish-coalescing operator (??) to use an empty string instead of undefined when concatenating.
const data = [
{ "personId": "1208007855" , "details": { "Closed": "12" } },
{ "personId": "1559363884" , "details": { "Closed": "12" } },
{ "personId": "0000000000" , "details": { "Open" : "8" } }, // New!
{ "personId": "973567318" , "details": { "Closed": "12" } }
];
const value = data.reduce((res, { details: { Closed } }) => res + (Closed ?? ''), '');
console.log(value);
If you want to implement using loops Try Using:
const data = [
{
"personId": "1208007855",
"details": {
"Closed": "12"
}
},
{
"personId": "1559363884",
"details": {
"Closed": "12"
}
},
{
"personId": "973567318",
"details": {
"Closed": "12"
}
}
];
var res= ''
data.forEach((item)=>{if(item.details.Closed){ res += item.details.Closed;}})
console.log(res)
And this can also be done by using higher order functions:
Try using :
data.reduce((res, item) =>{if(item.details.Closed)
res += item.details.Closed;
return res}, '')
This question already has answers here:
Most efficient method to groupby on an array of objects
(58 answers)
Closed 3 years ago.
I have an array of objects that looks like this:
let stuff = [
{
"id": "48202847",
"name": "Doe"
},
{
"id": "17508",
"name": "Marie"
},
{
"id": "175796",
"name": "Robert"
},
{
"id": "175796",
"name": "Ronald"
},
]
What I want to get is a dictionary looking something like this:
{
"D": [{"id": "48202847", "name": "Doe"}],
"M": [{"id": "17508", "name": "Marie"}],
"R": [{"id": "175796", "name": "Robert"}, {"id": "175796", "name": "Ronald"}]
}
Notice how all the people whose name starts with "R" are listed under one key.
This is my function that creates a dictionary with the person's name as the key:
const byId = (array) =>
array.reduce((obj, item) => {
obj[item.name] = item
return obj
}, {})
But this obviously doesn't do what I want it to. I do have some ideas of how to make this possible, but they are extremely legacy and I would love to know how to do this right.
Any help is appreciated!
You need the first character, uppercase and an array for collecting the objects.
const byId = array =>
array.reduce((obj, item) => {
var key = item.name[0].toUpperCase(); // take first character, uppercase
obj[key] = obj[key] || []; // create array if not exists
obj[key].push(item); // push item
return obj
}, {});
let stuff = [{ id: "48202847", name: "Doe" }, { id: "17508", name: "Marie" }, { id: "175796", name: "Robert" }, { id: "175796", name: "Ronald" }],
result = byId(stuff)
console.log(result);
Here's a solution based on Set, map, reduce and filter:
let stuff = [{"id": "48202847","name": "Doe"},{"id": "17508","name": "Marie"},{"id": "175796","name": "Robert"},{"id": "175796","name": "Ronald"}];
let result = [...new Set(stuff.map(x => x.name[0]))]
.reduce((acc, val) => {
return acc = { ...acc,
[val]: stuff.filter(x => x.name.startsWith(val))
}
}, {});
console.log(result);
Great solution Nina! Could be made a little cleaner by utilizing the spread operator.
const byId = (array) =>
array.reduce((obj, item) => {
var key = item.name[0].toUpperCase();
return {
...obj,
[key]: obj[key] ? [...obj[key], item] : [item],
}
}, {});
i'm trying to iterate recursively over nested objects to get the key and the value.
My data structure is:
{
"id": 8743077530231325861,
"name": "Name of XYZ",
"key X": 0,
"key Y": {
"details": {
"value": {
"up": 5,
"down": 3
},
"path": "xyz"
},
"key Z": {
"value": 1,
"path": "abc"
}
},
"createdTimestamp": 1554446703000
}
and my function is:
recursion = (item, keyString) => {
if(isObject(item)){
Object.keys(item).map((key) => {
return this.recursion(item[key], keyString+`.${key}`)
})
}else{
return {item, keyString}
}
}
and i call it by:
Object.keys(data).map(key =>{
console.log(this.recursion(data[key], key))
})
My problem is that keys which are objects are always undefined.
I know thats because they need to iterate an other time and the output is faster then the function. When i print out the values at the end of the recursion function instead of returning them, they are not undefined.
At the end i want for every key all the deepest values and "paths". For Example
8743077530231325861,"id"
Name of XYZ,"name"
0, "keyX"
5, "keyY.details.value.up"
...
I already tried to use await / async but i cant manage to get all values
would be nice if someone have a hint for me
You need to return the result of mapping.
const
isObject = v => v && typeof v === 'object',
recursion = (item, path = '') => isObject(item)
? Object
.keys(item)
.flatMap(k => recursion(item[k], path + (path && '.') + k))
: { item, path };
var data = { id: 8743077530231326000, name: "Name of XYZ", "key X": 0, "key Y": { details: { value: { up: 5, down: 3 }, path: "xyz" }, "key Z": { value: 1, path: "abc" } }, createdTimestamp: 1554446703000 },
result = recursion(data);
console.log(result);
This question already has answers here:
How to remove all duplicates from an array of objects?
(77 answers)
Closed 3 years ago.
How to remove complete record of same object in array please help me this, I am using below funtion but its only remove one value I want remove complete object of same object
var data = [{
"QuestionOid": 1,
"name": "hello",
"label": "world"
}, {
"QuestionOid": 2,
"name": "abc",
"label": "xyz"
}, {
"QuestionOid": 1,
"name": "hello",
"label": "world"
}];
function removeDumplicateValue(myArray) {
var newArray = [];
$.each(myArray, function (key, value) {
var exists = false;
$.each(newArray, function (k, val2) {
if (value.QuestionOid == val2.QuestionOid) { exists = true };
});
if (exists == false && value.QuestionOid != undefined) { newArray.push(value); }
});
return newArray;
}
I want result like this
[{
"QuestionOid": 2,
"name": "abc",
"label": "xyz"
}]
You can use reduce.
var data = [{"QuestionOid": 1,"name": "hello","label": "world"}, {"QuestionOid": 2,"name": "abc","label": "xyz"}, {"QuestionOid": 1,"name": "hello","label": "world"}];
let op = data.reduce((op,inp)=>{
if(op[inp.QuestionOid]){
op[inp.QuestionOid].count++
} else {
op[inp.QuestionOid] = {...inp,count:1}
}
return op
},{})
let final = Object.values(op).reduce((op,{count,...rest})=>{
if(count === 1){
op.push(rest)
}
return op
},[])
console.log(final)
Do with Array#filter.Filter the array matching QuestionOid value equal to 1
var data = [{ "QuestionOid": 1, "name": "hello", "label": "world" }, { "QuestionOid": 2, "name": "abc", "label": "xyz" }, { "QuestionOid": 1, "name": "hello", "label": "world" }]
var res = data.filter((a, b, c) => c.map(i => i.QuestionOid).filter(i => i == a.QuestionOid).length == 1)
console.log(res)