Create array of object with condition - javascript

I am creating array of object. I want to add object based on condition. But, It add false instead of not adding object in array.
I tried:
const flag = false;
const list = [
{ key: 'abc', label: 'abcd' },
flag && { key: 'bbb', label: 'abcd' },
{ key: 'ccc', label: 'abcd' },
flag && { key: 'ddd', label: 'abcd' },
{ key: 'eee', label: 'abcd' },
];
console.log(list);
You can check output there are false in array.

Assuming that all elements that are to be kept in the array do not have falsey values, you could simply filter them based on the value afterwards like so:
const flag = false;
const list = [
{ key: 'abc', label: 'abcd' },
flag && { key: 'bbb', label: 'abcd' },
{ key: 'ccc', label: 'abcd' },
flag && { key: 'ddd', label: 'abcd' },
{ key: 'eee', label: 'abcd' }
].filter(Boolean);
console.log("list:", list);
const flag2 = true;
const list2 = [
{ key: 'abc', label: 'abcd' },
flag2 && { key: 'bbb', label: 'abcd' },
{ key: 'ccc', label: 'abcd' },
flag2 && { key: 'ddd', label: 'abcd' },
{ key: 'eee', label: 'abcd' }
].filter(Boolean);
console.log("list2:", list2);

To do it all in a single statement, you can use the spread operator:
const list = [
{ key: 'abc', label: 'abcd' },
...(flag ? [{ key: 'bbb', label: 'abcd' }] : []),
{ key: 'ccc', label: 'abcd' },
...(flag ? [{ key: 'ddd', label: 'abcd' }] : []),
{ key: 'eee', label: 'abcd' },
];
It's pretty ugly though.

Related

JavaScript - update deeply nested array of objects with the target path

The nesting level is always unknown, and children can be either undefined or an array with at least one item. Each key is always unique. This would be an example:
const arr = [{
key: '001',
children: [{
key: 'abc',
children: [{
key: 'ee',
children: [{
key: 'goc',
}, {
key: 'zzv',
children: [{
key: '241',
}],
}],
}],
}, {
key: '125',
children: undefined,
}],
}, {
key: '003',
children: [{
key: 'ahge',
}, {
key: '21521',
}],
}];
I'd like to write a function that receives a key to find the element and then updates its children field with the given children array and then returns the whole arr.
// Function that returns arr with updated the target element - how can I write this?
const mysteryFn = (arr, key, childrenToUpdate) => {
// Do something..
return arr;
}
const key = 'goc';
const childrenToUpdate = [{
key: '12345',
}, {
key: '25221a',
}];
const newArr = mysteryFn(arr, key, childrenToUpdate);
// expected newArr
const newArr= [{
key: '001',
children: [{
key: 'abc',
children: [{
key: 'ee',
children: [{
key: 'goc',
children: [{
key: '12345',
}, {
key: '25221a',
}],
}, {
key: 'zzv',
children: [{
key: '241',
}],
}],
}],
}, {
key: '125',
children: undefined,
}],
}, {
key: '003',
children: [{
key: 'ahge',
}, {
key: '21521',
}],
}];
This can be achieved with recursion.
const mysteryFn = (arr, key, childrenToUpdate) => {
// if children are undefined
if (!arr) return;
// loop over each entry and its children to find
// entry with passed key
arr.forEach((entry) => {
if (entry.key === key) {
entry.children = childrenToUpdate;
}
// recursive call to traverse children
mysteryFn(entry.children, key, childrenToUpdate);
});
return arr;
};

Typescript Interface Definition dynamic

I am trying to define an interface for the following data:
result =
{
"data1" : [ { "type1" : 30 }, { "type2" :40 } ],
"data1" : [ { "abc" : 40 }, { "def" 940 } ],
"data3" : []
}
here the keys and values inside result object are dynamic. Even the values inside array of objects are dynamic but it will be of format string: number or that array can be empty just as in data3.
I tried using [x:any]: any, but looks like it will remove the significance of rest of the types defined in interface as it will match eveything.
Can someone help me here?
You can define dynamic key interface as follows:
interface Result {
[key: string]: {
[childKey: string]: number;
}[];
}
Something similar you can do -->
You don't need to use an indexer (since it a bit less typesafe). You have two options :
interface EnumServiceItem {
id: int; label: string; key: any
}
interface EnumServiceItems extends Array<EnumServiceItem>{}
// Option A
var result: EnumServiceItem[] = [
{ id: 0, label: 'CId', key: 'contentId' },
{ id: 1, label: 'Modified By', key: 'modifiedBy' },
{ id: 2, label: 'Modified Date', key: 'modified' },
{ id: 3, label: 'Status', key: 'contentStatusId' },
{ id: 4, label: 'Status > Type', key: ['contentStatusId', 'contentTypeId'] },
{ id: 5, label: 'Title', key: 'title' },
{ id: 6, label: 'Type', key: 'contentTypeId' },
{ id: 7, label: 'Type > Status', key: ['contentTypeId', 'contentStatusId'] }
];
// Option B
var result: EnumServiceItems = [
{ id: 0, label: 'CId', key: 'contentId' },
{ id: 1, label: 'Modified By', key: 'modifiedBy' },
{ id: 2, label: 'Modified Date', key: 'modified' },
{ id: 3, label: 'Status', key: 'contentStatusId' },
{ id: 4, label: 'Status > Type', key: ['contentStatusId', 'contentTypeId'] },
{ id: 5, label: 'Title', key: 'title' },
{ id: 6, label: 'Type', key: 'contentTypeId' },
{ id: 7, label: 'Type > Status', key: ['contentTypeId', 'contentStatusId'] }
]
Personally I recommend Option A (simpler migration when you are using classes not interfaces).

Find a nested object inside an arrary of objects based on the string

I've an array of objects in which I need to find the object which has the same value as that of the string.
I've tried this and it works.
But, is there a way to optimize it without using map?
Code:
const arr = [{
label: 'A',
options: [{
label: 'abc',
value: 'abc'
},
{
label: 'bcd',
value: 'bcd'
}
]
},
{
label: 'B',
options: [{
label: 'cde',
value: 'cde'
},
{
label: 'def',
value: 'def'
}
]
},
{
label: 'C',
options: [{
label: 'efg',
value: 'efg'
},
{
label: 'fgh',
value: 'fgh'
}
]
}
];
const str = 'cde';
const result = arr.map(obj => obj.options.find(item => item.value === str)).find(val => val !== undefined);
console.log('result', result);
Yes, you don't need or want map followed by find. Just a loop:
let result;
for (const obj of arr) {
result = obj.options.find(({value}) => value === str);
if (result) {
break;
}
}
Live Example:
const arr = [{
label: 'A',
options: [{
label: 'abc',
value: 'abc'
},
{
label: 'bcd',
value: 'bcd'
}
]
},
{
label: 'B',
options: [{
label: 'cde',
value: 'cde'
},
{
label: 'def',
value: 'def'
}
]
},
{
label: 'C',
options: [{
label: 'efg',
value: 'efg'
},
{
label: 'fgh',
value: 'fgh'
}
]
}
];
const str = 'cde';
let result;
for (const obj of arr) {
result = obj.options.find(({value}) => value === str);
if (result) {
break;
}
}
console.log('result', result);
You could take Array#flatMap with an empty array as default value.
The result is an array with matching result.
const
arr = [{ label: 'A', options: [{ label: 'abc', value: 'abc' }, { label: 'bcd', value: 'bcd' }] }, { label: 'B', options: [{ label: 'cde', value: 'cde' }, { label: 'def', value: 'def' } ] }, { label: 'C', options: [{ label: 'efg', value: 'efg' }, { label: 'fgh', value: 'fgh' }] }];
str = 'cde';
result = arr.flatMap(obj => obj.options.find(item => item.value === str) || []);
console.log('result', result);
you don't need to use find inside the map which is O(nk);
You can fetch all the options then flat the array to find the required object.
const arr = [{
label: 'A',
options: [{
label: 'abc',
value: 'abc'
},
{
label: 'bcd',
value: 'bcd'
}
]
},
{
label: 'B',
options: [{
label: 'cde',
value: 'cde'
},
{
label: 'def',
value: 'def'
}
]
},
{
label: 'C',
options: [{
label: 'efg',
value: 'efg'
},
{
label: 'fgh',
value: 'fgh'
}
]
}
];
const str = 'cde';
const result = arr.map(({options}) => options).flat().find(({value}) => value === str)
console.log('result', result);
Depending of your needs, you can do this:
const arr = [{ label: 'A', options: [{ label: 'abc', value: 'abc' }, { label: 'bcd', value: 'bcd' }] }, { label: 'B', options: [{ label: 'cde', value: 'cde' }, { label: 'def', value: 'def' } ] }, { label: 'C', options: [{ label: 'efg', value: 'efg' }, { label: 'fgh', value: 'fgh' }] }];
const re1 = /"value":"cde"/
const testStr = JSON.stringify(arr);
console.log(""+testStr)
console.log(re1.test(testStr)) // exists
const re2 = /"label":"(\w)+","value":"cde"/g
console.log(testStr.match(re2)) // label
find in the underscore library will avoid using map in this scenario:
var myObj = _.find(arr, (obj) => {
return _.find(obj.options, (elt) => elt.value === str);
});

Javascript - Assign object item with values from another object

I have an object with few items and I want to update the values of one property options from another object.
Object 1 :
structure = [
{
id: 'name',
label: 'Name',
filterType: 'text',
filterOn: 'contains'
},
{
id: 'address',
label: 'Address',
filterType: 'text',
filterOn: 'contains'
},
{
id: 'phone',
label: 'Phone',
filterType: 'select',
filterOn: 'contains',
options: [{ label: 'abc', value: 'abc' },
{ label: 'xyz', value: 'xyz' },
{ label: 'mno', value: 'mno' }]
}
];
if the id is phone then I want to get the values from the object 2 phoneList and assign it to the options instead of hard coding it.
options: [{ label: 'abc', value: 'abc' },
{ label: 'xyz', value: 'xyz' },
{ label: 'mno', value: 'mno' }]
}
];
object 2 is
this.props.phoneList = [{name: 'aaa', age: 11},{name : 'bbb' , age : 12}, and so on
]
label and values will be this.props.phoneList[i].name
how to loop over this and get the latest values from the other object
First use filter to identify the object with id phone. Then use map to transform this.probs.phoneList in the desired format and assign to options.
structure.filter (x => x.id == 'phone')[0].options = this.probs.phoneList.map (x => ({label: x.name, value: x.name}));

How to group array

I am trying to group similar objects with the same label.
At the moment, this is the the JSON I receive.
const sizes = [{
id: [{
value: '2496',
label: 'XS'
}, {
value: '2499',
label: 'S'
}],
type: 'First Size'
}, {
id: [{
value: '2863',
label: 34
}, {
value: '2866',
label: 36
}],
type: 'Shoe Sizes'
}, {
id: [{
value: '3561',
label: 'XS'
}, {
value: '3563',
label: 'S'
}, {
value: '3565',
label: 'L'
}, , {
value: '3567',
label: 'XL'
}]
}, {
id: [{
value: '3523',
label: 34
}, {
value: '2866',
label: 36
}],
type: 'Shoe Sizes'
}]
The result I am trying to achieve is
const sizes = [{
id: [{
value: '2496,3561',
label: 'XS'
}, {
value: '2499,3563',
label: 'S'
}],
type: 'First Size'
}, {
id: [{
value: '2863,3523',
label: 34
}, {
value: '2866',
label: 36
}],
type: 'Shoe Sizes'
}, {
id: [{
value: '3565',
label: 'L'
}, , {
value: '3567',
label: 'XL'
}]
}, {
id: [{
value: '2866',
label: 37
}],
type: 'Shoe Sizes'
}]
I have tried to achieve this with underscore, but I am only able to group it by just one label, and I need to group it by any kind of label, whether it be XS or 36.
I have tried with reduce below, it is close but I just need to remove the brackets around the value, and turn the value into a string.
EX: value: '2493, 2343'
var group_to_values = sizes.reduce(function (obj, item) {
obj[item.label] = obj[item.label] || [];
obj[item.label].push(item.value);
return obj;
}, {});
var groups = Object.keys(group_to_values).map(function (key) {
return {label: key, value: group_to_values[key]};
});
You could take a hash table for same labels and iterate the outer array and the inner array. If a label is not found, it generates a new entry for the result set.
var sizes = [{ id: [{ value: '2496', label: 'XS' }, { value: '2499', label: 'S' }], type: 'First Size' }, { id: [{ value: '2863', label: 34 }, { value: '2866', label: 36 }], type: 'Shoe Sizes' }, { id: [{ value: '3561', label: 'XS' }, { value: '3563', label: 'S' }, { value: '3565', label: 'L' }, { value: '3567', label: 'XL' }] }, { id: [{ value: '3523', label: 34 }, { value: '2866', label: 36 }], type: 'Shoe Sizes' }],
labels = Object.create(null),
joined = sizes.reduce((r, a) => {
var temp;
a.id.forEach(o => {
if (labels[o.label]) {
labels[o.label].value += ',' + o.value;
return;
}
if (!temp) {
temp = Object.assign({}, a, { id: [] });
r.push(temp);
}
temp.id.push(labels[o.label] = o);
});
return r;
}, []);
console.log(joined);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Here you are, the code below would output Array called result, which is data set you desired, the loop is clear so I think it won't be an issue for you to go through it:
const sizes = [{
id: [{
value: '2496',
label: 'XS'
}, {
value: '2499',
label: 'S'
}],
type: 'First Size'
}, {
id: [{
value: '2863',
label: 34
}, {
value: '2866',
label: 36
}],
type: 'Shoe Sizes'
}, {
id: [{
value: '3561',
label: 'XS'
}, {
value: '3563',
label: 'S'
}, {
value: '3565',
label: 'L'
}, {
value: '3567',
label: 'XL'
}]
}, {
id: [{
value: '3523',
label: 34
}, {
value: '2866',
label: 36
}],
type: 'Shoe Sizes'
}]
var groupedSizes = {};
for (var current, i=0;i < sizes.length ;i++){
for (var j=0;j < sizes[i]['id'].length;j++) {
current = sizes[i]['id'][j]
if (groupedSizes[current['label']] !== undefined) {
groupedSizes[current['label']].push(current['value'])
} else {
groupedSizes[current['label']] = [current['value']]
}
}
}
var result = []
for (var key in groupedSizes) {
result.push({'id': groupedSizes[key].join(','), 'label': key})
}
console.log(result)

Categories