Let's say I have array of objects - original items
originalItems = [
{name:"aaa", expanded: false, visible: true},
{name:"bbb", expanded: false, visible: true},
{name:"ccc", expanded: false, visible: true}
]
then I do some changes on items
currentItems = [
{name:"aaa", expanded: true, visible: false},
{name:"bbb", expanded: false, visible: true},
{name:"ccc", expanded: true, visible: true}
]
Now I need to merge those two arrays,
BUT: in the merged arrays (result), I need that expanded value will be from currentItems, and visible will be from originalItems
something like this
result = [
{name:"aaa", expanded: true, visible: true},
{name:"bbb", expanded: false, visible: true},
{name:"ccc", expanded: true, visible: true}
]
Is there some elegant way to achieve it? Or just go through properties?
You can use .map() on one of the arrays, for example the original one, and transform each object into a new object by spreading the properties of the original object (...) into a new object. You can then set the expanded property to take the value from its corresponding object in the currentItems via the index (i). See example below:
const originalItems = [ {name:"aaa", expanded: false, visible: true}, {name:"bbb", expanded: false, visible: true}, {name:"ccc", expanded: false, visible: true} ];
const currentItems = [ {name:"aaa", expanded: true, visible: false}, {name:"bbb", expanded: false, visible: true}, {name:"ccc", expanded: true, visible: true} ];
const res = originalItems.map((obj, i) => ({
...obj,
expanded: currentItems[i].expanded
}));
console.log(res);
I'd sort and manage arrays like this, for simplicity as well speed. Perhaps more on par with what you were looking to do.
let Items = [
{ name: "aaa", expanded: false, visible: true },
{ name: "bbb", expanded: false, visible: true },
{ name: "ccc", expanded: false, visible: true }
]
function doExpand(name, val) {
let item = getItem(name);
item.expanded = val;
}
function doVisible(name, val) {
let item = getItem(name);
item.visible = val;
}
function addItem(name) {
if (!getItem(name)) {
Items.push({ name: name, expanded: false, visible: false });
} else {
console.log("duplicates found");
}
}
function getItem(name) {
for (let i = 0; i < Items.length; i++) {
if (Items[i].name === name) return Items[i];
}
return false;
}
/* TESTING TIME */
doExpand("aaa", true);
doExpand("aaa", false);
let Item = getItem("bbb");
Item.name = "renamed";
addItem("dogsnacks");
addItem("bacon");
addItem("programming");
addItem("programming");
addItem("programming");
addItem("programming");
addItem("programming");
console.log(Items);
Since you're taking the elements from two different arrays of the same length to create a third, you can create a new array, then loop through the number of objects in the array, constructing your result object based on the desired source list.
let result = [];
for (i = 0; i < originalItems.length; i++) {
let newObj = {
name: originalItems[i].name,
expanded: currentItems[i].expanded,
visible: originalItems[i].visible,
};
result.push(newObj);
}
Related
I have two arrays
const condition = [
{ iosSend: true },
{ androidSend: true }
]
const myArray = [
{
androidSend: false,
iosSend: true,
macosSend: false,
id: 1
},
{
androidSend: true,
iosSend: false,
macosSend: false,
id: 2
},
{
androidSend: true,
iosSend: true,
macosSend: false,
id: 3
},
{
androidSend: false,
iosSend: false,
macosSend: true,
id: 4
}
]
Where I want to filter myArray with the following conditions:
Return a array with objects that has at least one of the keys of object inside condition array Equals false.
I mean, in the example, the return should return an array
with objects with ids 1, 2 and 4
Which is the best way to do this?
The following is an example of filtering if you wanted all items that match any condition.
const condition = {
iosSend: false,
androidSend: false
};
const myArray = [
{
androidSend: false,
iosSend: true,
macosSend: false,
id: 1
},
{
androidSend: true,
iosSend: false,
macosSend: false,
id: 2
},
{
androidSend: true,
iosSend: true,
macosSend: false,
id: 3
},
{
androidSend: false,
iosSend: false,
macosSend: true,
id: 4
}
];
const conditions = Object.entries(condition);
const filteredArr = myArray.filter(o => {
for (const [key, val] of conditions) {
if (key in o && o[key] == val) return true;
}
return false;
});
console.log(filteredArr);
#EDIT:
I changed conditions to be either iosSend false or androidSend false after clarifying comment from author
This is my array:
array: [{
_id: 5f62b2bc84a1ef1c5c48d1af,
eeid: '300094E6E2',
adminOrganization: true,
adminEmployees: false,
adminAssets: true,
adminConsumables: true,
adminWarehousing: false,
grantBy: '300094E6E2',
grantDate: 2020-10-04T11:46:28.548Z,
__v: 0
}]
I want to filter only true values and display only the key: Below is my desired result:
resultingArray = ['adminOrganization', 'adminAssets', 'adminConsumables']
You can use Object.key to get all keys in object and filter field value is true as
var filtered = Object.keys(obj[0]).filter(function(key) {
return obj[0][key] == true;
});
obj = [{
_id: '5f62b2bc84a1ef1c5c48d1af',
eeid: '300094E6E2',
adminOrganization: true,
adminEmployees: false,
adminAssets: true,
adminConsumables: true,
adminWarehousing: false,
grantBy: '300094E6E2',
grantDate: '2020-10-04T11:46:28.548Z',
__v: 0
}]
;
var filtered = Object.keys(obj[0]).filter(function(key) {
return obj[0][key] == true;
});
console.log(filtered)
I have a set of input fields with checkboxes where the user can choose an option. Then it's saved in local storage as true if checked and false if not. The localStorage under key "passengers" looks like this:
0: {name: "", child: false, luggage: true}
1: {name: "", child: true, luggage: false}
2: {name: "", child: false, luggage: true}
3: {name: "", child: true, luggage: false}
I want to count occurrences of true and store as a number in a variable
public luggageCounter: number;
I was trying to use
this.luggageCounter = countTrue([this.passengers[i].luggage]], true)
console.log(this.luggageCounter)
and const countTrue = (arr, val) => arr.reduce((a, v) => (v === val ? a +1 : a), 0)
but both of these solutions don't work. I was also thinking about making it easier and toggling the value from HTML by adding code below with [ngClass] and binding it with method in component.ts but also with no success.
<div>Extra luggage: {{ passengers[i].luggage ? 'Yes' : 'No' }}<div>
Any ideas how to make this simple task work? I'm out of ideas :)
Please try the following solution
const data = [
{ name: "", child: false, luggage: true },
{ name: "", child: true, luggage: false },
{ name: "", child: false, luggage: true },
{ name: "", child: true, luggage: false },
];
const total = data.reduce((previousValue, currentValue) => {
if (currentValue.luggage) {
previousValue += 1;
}
return previousValue;
}, 0);
console.log(total);
See
Array.prototype.reduce()
How can I pass object keys into an array that are true. So that I can use this array for filtering?
Example Object:
let results = [
{name: marc, isAlumnus: true, isScholar: true, isTrustee: false},
{name: franz, isAlumnus: false, isScholar: true, isTrustee: false},
{name: Hugo, isAlumnus: true, isScholar: true, isTrustee: false},
]
And the attempt of a function!
getActiveStatusGroups (results) {
let res = [];
res = results.map((item) => {
if (item) {
res.push('isScholar');
}
});
return res;
},
let statusArray = getActiveStatusGroup(this.results)
You can get an array of the property names from Object.keys, or an array of [name, value] arrays from Object.entries, depending on what you want to do.
It's kind of hard to tell what output you want as a result, but for instance, this returns an array of arrays, where the inner arrays are the names of the properties for which the value was truthy:
getActiveStatusGroups(results) {
return results.map(entry =>
Object.keys(entry).filter(key => entry[key])
);
}
Live Example:
let results = [
{isAlumnus: true, isScholar: true, isTrustee: false},
{isAlumnus: false, isScholar: true, isTrustee: false},
{isAlumnus: true, isScholar: true, isTrustee: false},
];
function getActiveStatusGroups(results) {
return results.map(entry =>
Object.keys(entry).filter(key => entry[key])
);
}
console.log(getActiveStatusGroups(results));
Filtering is pretty simple in JavaScript
The methods name is right there in your title, yet you failed to recognize it. Use filter instead of map. The filter() method creates a new array with all elements that pass the test implemented by the provided function.
Here's your code
let results = [
{name: marc, isAlumnus: true, isScholar: true, isTrustee: false},
{name: franz, isAlumnus: false, isScholar: true, isTrustee: false},
{name: Hugo, isAlumnus: true, isScholar: true, isTrustee: false},
]
getActiveStatusGroups(group) {
// returns the element if the condition is true
return results.filter(result => result[group])
}
That's it
console.log(getActiveStatusGroups('isAlumnus'))
console.log(getActiveStatusGroups('isScholar'))
console.log(getActiveStatusGroups('isTrustee'))
I have a config.ts file with following content:
export const keyOrders: {} = {
"aa": { active: true, order: 0 },
"bb": { active: true, order: 1 },
"cc": { active: true, order: 2 },
"dd": { active: true, order: 3 },
"ee": { active: false, order: 4 },
"ff": { active: true, order: 5 }
};
I am trying to push to array if active is only true. I have tried following code which is pushing key if active is true but if active is false then it is returning "undefined"
public keys = [];
public keyOrders = keyOrders;
ngOnInit() {
this.keys = Object.entries(this.keyOrders).map((a: any) => {
if(a[1].active == 'true') {
return a[0];
}
});
}
Use filter followed by map.
If you want to sort the items based on their order property, use sort before map.
filter will only keep items passing the predicate, in this case a truthy active property. Then map will map this array to the keys.
In your case, using map will give you an array of the same length, you must filter it first.
type Order = { active: boolean, order: number };
const keyOrders: { [key: string]: Order } = {
"aa": { active: true, order: 0 },
"bb": { active: true, order: 1 },
"cc": { active: true, order: 2 },
"dd": { active: true, order: 3 },
"ee": { active: false, order: 4 },
"ff": { active: true, order: 5 }
}
this.keys = Object.entries(this.keyOrders)
.filter(([_, val]) => val.active)
.sort((a, b) => a[1].order - b[1].order)
.map(([key, _]) => key);
For the types to work out, Object.entries() must be recognized by Typescript, for this, add "lib": [ "es2017.object" ] in your tsconfig.json file.
Here is a JavaScript demo (types stripped):
const keyOrders = {
"aa": { active: true, order: 0 },
"bb": { active: true, order: 1 },
"cc": { active: true, order: 2 },
"dd": { active: true, order: 3 },
"ee": { active: false, order: 4 },
"ff": { active: true, order: 5 }
};
const keys = Object.entries(keyOrders)
.filter(([_, val]) => val.active)
.sort((a, b) => a[1].order - b[1].order)
.map(([key, _]) => key);
console.log(keys);