sort items by two different properties javascript - javascript

I have an array of objects.
const people = [
{
active: true,
hasMoney: false
},
{
active: false,
hasMoney: false
},
{
active: true,
hasMoney: true
}
]
I want to sort the data in this order: active: true -> hasMoney: true -> active: false -> hasMoney: false
Important: If the user is active === true and hasMoney === true, then this should be ordered after active === true and hasMoney === false
I tried the following but it didn't work. Anyone have any ideas?
people
.sort((x, y) =>
x.hasMoney
? Number(x) - Number(y)
: Number(isPersonActive(y)) - Number(isPersonActive(x))
)

You could take the delta of the boolean values and sort by two properties with a special look to the sorting of same values.
const people = [{ active: false, hasMoney: true }, { active: true, hasMoney: false }, { active: false, hasMoney: false }, { active: true, hasMoney: true }];
people.sort((a, b) =>
b.active - a.active ||
(a.hasMoney === b.active) - (a.active === b.hasMoney)
);
console.log(people);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You can do the following,
const people = [
{
active: true,
hasMoney: true
},
{
active: false,
hasMoney: false
},
{
active: true,
hasMoney: false
}
]
people.sort((a, b) => {
if(a.active && b.active) {
return a.hasMoney - b.hasMoney;
} else if(a.active) {
return -1;
} else if(b.active) {
return 1;
} else {
return b.hasMoney - a.hasMoney;
}
})
console.log(people);

The following sort with a OR condition as per provided condition.
const people = [
{
active: true,
hasMoney: false
},
{
active: false,
hasMoney: false
},
{
active: false,
hasMoney: true
},
{
active: true,
hasMoney: false
}
];
const a = people.sort((a,b) => b.active-a.active || (b.hasMoney - a.hasMoney));
console.log(a);

const people = [
{
active: true,
hasMoney: true
},
{
active: false,
hasMoney: false
},
{
active: true,
hasMoney: false
},
{
active: false,
hasMoney: true
}
]
let peopleSorted = people.sort((a, b) => {
if (a.active == b.active) {
if (a.hasMoney < b.hasMoney) {
return 1;
} else if (a.hasMoney > b.hasMoney) {
return -1;
} else {
return 0;
}
} else if (a.active) {
return -1;
} else if (b.active) {
return 1;
} else {
return 0;
}
});
console.log(peopleSorted);

Try like this. when both are active (on campare), sort on hasMoney
const sort = (arr) => arr.sort((a, b) => {
if (a.active === b.active) {
return b.hasMoney - a.hasMoney;
}
return b.active - a.active;
})
const people = [
{
active: true,
hasMoney: false
},
{
active: false,
hasMoney: false
},
{
active: true,
hasMoney: true
}
]
const people2 = [
{ active: true, hasMoney: false },
{ active: false, hasMoney: false },
{ active: false, hasMoney: true },
{ active: true, hasMoney: true },
];
console.log(sort(people))
console.log(sort(people2))

Related

Filter Array with properties and values of another array - Javascript

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

How can i convert an object in a specific format into another format

I am having a hard time trying to convert an object supplied in a specific format from API into a target format using javascript. Please note that in the target format, the false values are not present. This is intentional. Can someone please help by showing how I can do the this kind of conversion. Thank you
// Original format
const rules= [
{
dealer: {
view: true,
edit: false,
add: false
},
franchise: {
view: true,
edit: true,
add: true
},
branch: {
view: true,
edit: false,
add: false
}
}
]
// Target format
const rules = [
{
actions: ["view"],
subject: ["dealer"]
},
{
actions: ["view"],
subject: ["franchise"]
},
{
actions: ["edit"],
subject: ["franchise"]
},
{
actions: ["add"],
subject: ["franchise"]
},
{
actions: ["view"],
subject: ["branch"]
}
];
I implemented mapping function which take each item and map it according to the value if true
let rules = [
{
dealer: {
view: true,
edit: false,
add: false
},
franchise: {
view: true,
edit: true,
add: true
},
branch: {
view: true,
edit: false,
add: false
}
}
]
rules = rules.map(item => {
const keys = Object.keys(item);
let mappedItem = []
keys.forEach(key => {
for (const property in item[key]) {
if (item[key][property]) {
mappedItem.push({ subject: [key], actions: [property] })
}
}
})
return mappedItem;
});
let rules= [
{
dealer: {
view: true,
edit: false,
add: false
},
franchise: {
view: true,
edit: true,
add: true
},
branch: {
view: true,
edit: false,
add: false
}
}
];
const result = rules.map(obj => Object.keys(obj).map(k => ({
subject: [k],
actions: Object.keys(obj[k]).filter(action => obj[k][action])
})).reduce((acc, cur) => ([
...acc,
...cur.actions.map(a => ({subject: cur.subject, actions: [a]}))
]),[]))
console.log(result);

How to push the data with specific status set?

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);

every object should have at least one true property value in array of objects?

i want to create a function to return true (each object should have at least one isValid:true) else return false.
const Items = [{
parentValidators: [{
isValid: true
}, {
isValid: false
}, {
isValid: false
}]
},
{
parentValidators: [{
isValid: true
}, {
isValid: false
}, {
isValid: false
}]
}
]
// i tried :
validateSection() {
Items.map(item => {
if (item.parentValidators) {
const logs = item.parentValidators;
return logs.map(l => {
return l.isValid ? true : l.isValid;
});
}
}).map((i, indx, arr) => {
let count = 0;
if (i.includes('true')) {
count++;
}
return count === array.length ? true : false;
})
}
A function to return true if every item in Items has at least one validator with an isValid value of true is the perfect use case for a combination of the array every and some methods:
const Items = [{
parentValidators: [{
isValid: true
}, {
isValid: false
}, {
isValid: false
}]
},
{
parentValidators: [{
isValid: true
}, {
isValid: false
}, {
isValid: false
}]
}
]
// i tried :
function validateSection() {
return Items.every(validators => validators.parentValidators.some(i => i.isValid));
}
console.log(validateSection())
Can use Array#some
const Items = [{
parentValidators: [{
isValid: true
}, {
isValid: false
}, {
isValid: false
}]
},
{
parentValidators: [{
isValid: false
}, {
isValid: false
}, {
isValid: false
}]
}
]
const res = Items.map(({parentValidators:v})=> v.some(({isValid:i})=>i))
console.log(res)

Diffrence between two Objects and add missing values

How to check diffrence between two Objects and add missing values?
Example: https://jsfiddle.net/aca0hdv9/
var defaultOptions = {
monit : {
map:{
googleMap: false
},
vehiclesList: {
rightSide: false,
number: true,
driver: true,
note: true,
},
vehicleCloud: {
speed: true,
date: true,
alarms: true,
fuelsCloud: true
},
driverCloud: true
};
var userCacheOptions = {
monit : {
// Missing map options
vehiclesList: {
rightSide: false,
number: false,
driver: false
// Missing note option
},
vehicleCloud: {
speed: true,
date: true,
alarms: true,
fuelsCloud: true
},
// Missing driverCloud option
}
};
I don't want to assign default values, i just want add missing values. Any idea how to do this in the least complicated way?
You can use Object.keys to get all ennumerable keys. From there, you simply have to iterate over them.
var defaultOptions = {
monit: {
map: {
googleMap: false
},
vehiclesList: {
rightSide: false,
number: true,
driver: true,
note: true,
},
vehicleCloud: {
speed: true,
date: true,
alarms: true,
fuelsCloud: true
},
driverCloud: true
}
};
var userCacheOptions = {
monit: {
// Missing map options
vehiclesList: {
rightSide: false,
number: false,
driver: false
// Missing note option
},
vehicleCloud: {
speed: true,
date: true,
alarms: true,
fuelsCloud: true
}
// Missing driverCloud option
}
};
function fillBlanks(receiver, giver) {
var receiverkeys = Object.keys(receiver);
var giverkeys = Object.keys(giver);
for(var i = 0; i < giverkeys.length; i++) {
if(typeof receiver[giverkeys[i]] != typeof giver[giverkeys[i]]) {
receiver[giverkeys[i]] = giver[giverkeys[i]];
}
if(receiver[giverkeys[i]] != giver[giverkeys[i]]) {
receiver[giverkeys[i]] = giver[giverkeys[i]];
}
}
}
fillBlanks(userCacheOptions.monit, defaultOptions.monit);
console.log(userCacheOptions.monit);
You could iterate over the keys and check for objects and call the function recursive with the new objects to check. If a value is missing, then set it to the default value.
function setDefault(user, def) {
Object.keys(def).forEach(function (k) {
if (def[k] !== null && typeof def[k] === 'object') {
if (!(k in user)) {
user[k] = {};
}
setDefault(user[k], def[k]);
return;
}
if (!(k in user)) {
user[k] = def[k];
}
});
}
var defaultOptions = { monit: { map: { googleMap: false }, vehiclesList: { rightSide: false, number: true, driver: true, note: true, }, vehicleCloud: { speed: true, date: true, alarms: true, fuelsCloud: true }, driverCloud: true } },
userCacheOptions = { monit: { vehiclesList: { rightSide: false, number: false, driver: false }, vehicleCloud: { speed: true, date: true, alarms: true, fuelsCloud: true }, } };
setDefault(userCacheOptions, defaultOptions);
console.log(userCacheOptions);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I would do this job as follows; It recursively iterates and modifies the userCacheOptions object at place.
var defaultOptions = {
monit : {
map:{
googleMap: false
},
vehiclesList: {
rightSide: false,
number: true,
driver: true,
note: true,
},
vehicleCloud: {
speed: true,
date: true,
alarms: true,
fuelsCloud: true
},
driverCloud: true
}
};
var userCacheOptions = {
monit : {
// Missing map options
vehiclesList: {
rightSide: false,
number: false,
driver: false
// Missing note option
},
vehicleCloud: {
speed: true,
date: true,
alarms: true,
fuelsCloud: true
},
// Missing driverCloud option
}
};
function restoreMissing(def,obj){
Object.keys(def).map(k => (typeof def[k] === "object" &&
typeof obj[k] === "object") ? restoreMissing(def[k],obj[k])
: !obj[k] && (obj[k] = def[k]));
return obj;
}
console.log(restoreMissing(defaultOptions,userCacheOptions))
This is the pattern that you want to follow, you just add the appropriate actions for each check.
if(!(defaultOptions.equals(userCacheOptions))){
//check for userCacheOptions if the value is set
//if its not set then set it as you want
if(!(userCacheOptions.getGoogleMap().isSet())){
userCacheOptions.setGoogleMap("whatever you want to set");
}
//same each variable etc
}

Categories