Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 days ago.
This post was edited and submitted for review 3 days ago.
Improve this question
I'm dealing with object array
var data = [
{
"rdd": "Transducer Failure",
"performance": true,
"agc": true,
"snr": true,
"sos": true,
"flowvel": true
},
{
"rdd": "Detection Problem",
"performance": false,
"agc": false,
"snr": false,
"sos": false,
"flowvel": false
},
{
"rdd": "Ultrasonic Noise",
"performance": false,
"agc": false,
"snr": false,
"sos": false,
"flowvel": false
},
{
"rdd": "Process Condition Pressure",
"performance": false,
"agc": false,
"snr": false,
"sos": false,
"flowvel": false
},
{
"rdd": "Process Condition Temperature",
"performance": false,
"agc": true,
"snr": false,
"sos": true,
"flowvel": false
},
{
"rdd": "Fouling",
"performance": false,
"agc": false,
"snr": false,
"sos": false,
"flowvel": false
},
{
"rdd": "Changes in flow profile",
"performance": false,
"agc": false,
"snr": false,
"sos": false,
"flowvel": false
},
{
"rdd": "High Velocity",
"performance": true,
"agc": true,
"snr": true,
"sos": false,
"flowvel": false
}
]
Now I want to invert value of object, whichever is false make true and vice verse. also, need to extract key's whose value is True after inversion .. I tried couple of things but no luck.
any idea ??
EDIT :
I Tried using
console.log(data);
for (var key in data) {
var obj = data[key];
Object.entries(obj).forEach(([key, value]) => {
if(value == false){
value = true;
}
})
}
console.log(data)
result remains same
You could check the type of value and get the negated value or value of not boolean.
const
data = [{ rdd: "Transducer Failure", performance: true, agc: true, snr: true, sos: true, flowvel: true }, { rdd: "Detection Problem", performance: false, agc: false, snr: false, sos: false, flowvel: false }, { rdd: "Ultrasonic Noise", performance: false, agc: false, snr: false, sos: false, flowvel: false }, { rdd: "Process Condition Pressure", performance: false, agc: false, snr: false, sos: false, flowvel: false }, { rdd: "Process Condition Temperature", performance: false, agc: true, snr: false, sos: true, flowvel: false }, { rdd: "Fouling", performance: false, agc: false, snr: false, sos: false, flowvel: false }, { rdd: "Changes in flow profile", performance: false, agc: false, snr: false, sos: false, flowvel: false }, { rdd: "High Velocity", performance: true, agc: true, snr: true, sos: false, flowvel: false }],
result = data.map(o => Object.fromEntries(Object
.entries(o)
.map(([k, v]) => [k, typeof v === 'boolean' ? !v : v])
));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I need to convert an array of boolean values indicating whether the store is open on a given day.
For example:
Case 1:
Input data: [true, true, true, true, true, true, true]
Expected output: Every day
Case 2:
Input data: [true, true, true, true, true, false, false]
Expected output: Mon-Fri
Case 3:
Input data: [true, true, false, false, true, true, true]
Expected output: Mon-Tue, Fri-Sun
Case 4:
Input data: [true, false, false, true, false, false, true]
Expected output: Mon, Thu, Sun
Case 5:
Input data: [true, true, false, true, true, true, false]
Expected output: Mon-Tue, Thu-Sat
Case 6:
Input data: [true, false, false, false, false, false, false]
Expected output: Only Monday
I came up with this, but need help with cases 2-5
const daysLabels = [
{ label: "Monday", short: "Mon" },
{ label: "Tuesday", short: "Tue" },
{ label: "Wednesday", short: "Wed" },
{ label: "Thursday", short: "Thu" },
{ label: "Friday", short: "Fri" },
{ label: "Saturday", short: "Sat" },
{ label: "Sunday", short: "Sun" }
];
const getSchedule = ({ case: days }) => {
let activeDays = [];
for (let i = 0; i < [...days].length; i++) {
const day = [...days][i];
if (day) {
activeDays.push({ ...daysLabels[i], value: day });
}
}
if (activeDays.length === 7) {
return "Every day";
}
if (activeDays.length === 1) {
return `Only ${activeDays[0].label}`;
}
return "#TODO";
};
Sandbox - link
Here's my answer, This is not an optimized version.
Add below function:-
function getWeekDuration(cases) {
let index = 0;
let weekDurationArray = [];
for (let i = 0; i < cases.length; i++) {
const day = cases[i];
if (i === 0) {
weekDurationArray[index] = [];
}
if (day) {
weekDurationArray[index].push({ ...daysLabels[i],
value: day
});
} else {
if (weekDurationArray[index].length > 0) {
index += 1;
weekDurationArray[index] = [];
}
}
}
// remove empty arrays
weekDurationArray = weekDurationArray.filter(item => item.length > 0);
// get only first and last day of each week duration
weekDurationArray = weekDurationArray.map(weekDuration => {
// concate inner array into string
if (weekDuration.length > 1) {
return `${weekDuration[0].short}-${weekDuration[weekDuration.length - 1].short}`;
}
return weekDuration[0].short;
});
return weekDurationArray.join(', ');
}
Add return the function from getSchedule
return getWeekDuration(days);
You can use Array.reduce() to create groups of day ranges, along with the correct labels.
We then use a Array.map() call to return only the label for each range.
I've added the 6 test cases mentioned, they should all pass.
const daysLabels = [
{ label: "Monday", short: "Mon" },
{ label: "Tuesday", short: "Tue" },
{ label: "Wednesday", short: "Wed" },
{ label: "Thursday", short: "Thu" },
{ label: "Friday", short: "Fri" },
{ label: "Saturday", short: "Sat" },
{ label: "Sunday", short: "Sun" }
];
function getDayRange(input) {
// Deal with 7 days and 1 day only first...
if (input.filter(active => active).length === 7) {
return 'Every day';
} else if (input.filter(active => active).length === 1) {
return `Only ${daysLabels[input.findIndex(active => active)].label}`;
}
// 2 - 6 days active
return input.reduce((acc, active, idx) => {
if (active) {
if (!acc.length || acc[acc.length - 1].end < (idx - 1) ) {
acc.push({ start: idx, end: idx, label: daysLabels[idx].short, startLabel: daysLabels[idx].short });
} else {
acc[acc.length - 1].end = idx;
acc[acc.length - 1].label = acc[acc.length - 1].startLabel + '-' + daysLabels[idx].short;
}
}
return acc;
}, []).map(r => r.label).join(', ');
}
const cases = [
{ input: [true, true, true, true, true, true, true], expected: 'Every day' },
{ input: [true, true, true, true, true, false, false], expected: 'Mon-Fri' },
{ input: [true, true, false, false, true, true, true], expected: 'Mon-Tue, Fri-Sun' },
{ input: [true, false, false, true, false, false, true], expected: 'Mon, Thu, Sun' },
{ input: [true, true, false, true, true, true, false], expected: 'Mon-Tue, Thu-Sat' },
{ input: [true, false, false, false, false, false, false], expected: 'Only Monday' },
]
console.log(`Case`, '\t', 'Pass', '\t', 'Output')
cases.forEach(({ input, expected }, idx) => {
let output = getDayRange(input);
console.log(`${idx + 1}`, '\t', output === expected, '\t', output)
})
.as-console-wrapper { max-height: 100% !important; }
I declare a mapping array for the text, below is the example code,and you can modify the text when function return only one day or everyday.
// for index mapping
let indexMapping = [
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun"
];
function getWeeks(arr){
let list = [];
let indexes = [];
let item = [];
// get all indexes
arr.forEach((result,index) => {
if(result) indexes.push(index);
});
// push each text to list
indexes.map(i => {
if(!indexes.includes(i-1)){
if(item.length == 1){
list.push(item[0]);
item = [];
}
item.push(indexMapping[i]);
}
else if(!indexes.includes(i+1)){
item.push(indexMapping[i]);
list.push(item.join("-"));
item = [];
}
});
// if indexes only has one item
if(item.length == 1){
list.push(item[0]);
}
return list;
}
// for test
let testArr2 = [true, true, true, true, true, false, false];
let testArr3 = [true, true, false, false, true, true, true];
let testArr4 = [true, false, false, true, false, false, true];
let testArr5 = [true, true, false, true, true, true, false];
getWeeks(testArr2); // output will be like ['Mon-Fri']
Use of Array#map with regular expressions may help have less hard-coding as follows:
const daysLabels = [
{ label: "Monday", short: "Mon" },
{ label: "Tuesday", short: "Tue" },
{ label: "Wednesday", short: "Wed" },
{ label: "Thursday", short: "Thu" },
{ label: "Friday", short: "Fri" },
{ label: "Saturday", short: "Sat" },
{ label: "Sunday", short: "Sun" }
],
getSchedule = ({ case: days }) => {
const out = days.map((b,i) => b ? daysLabels[i].short : ":")
.join(",").replace(/(?<![:\b]),[,A-za-z]*,(?![:\b])/g,"-")
.replace(/(?<=[a-z]),(?=[A-Z])/g,"-")
.replace(/[,\:]+/g,",").replace(/^[^A-Z]+|[^a-z]+$/g,"")
.replace(/,/g,", ");
return out === 'Mon-Sun' ? 'Every day' :
!out.match(/[\-,]/) ?
`Only ${daysLabels.find(({short}) => short === out).label}` :
out;
};
const cases = [
{ input: [true, true, true, true, true, true, true], expected: 'Every day' },
{ input: [true, true, true, true, true, false, false], expected: 'Mon-Fri' },
{ input: [true, true, false, false, true, true, true], expected: 'Mon-Tue, Fri-Sun' },
{ input: [true, false, false, true, false, false, true], expected: 'Mon, Thu, Sun' },
{ input: [true, true, false, true, true, true, false], expected: 'Mon-Tue, Thu-Sat' },
{ input: [true, false, false, false, false, false, false], expected: 'Only Monday' },
{ input: [false, false, false, true, false, false, false], expected: 'Only Thursday' },
{ input: [false, false, false, false, false, false, true], expected: 'Only Sunday' }
]
console.log(`Case`, '\t', 'Pass', '\t', 'Output')
cases.forEach(({ input, expected }, idx) => {
let output = getSchedule({case:input});
console.log(`${idx + 1}`, '\t', output === expected, '\t', output)
});
.as-console-wrapper { max-height: 100% !important; }
The following is a sample that yields the desired output.
const data = [
{ itemID: '300', status: 'active', inventoryFlag: true, certifiedFlag: false, donateFlag: true },
{ itemID: '400', status: 'inactive', inventoryFlag: true, certifiedFlag: true, donateFlag: false },
{ itemID: '500', status: 'active', inventoryFlag: false, certifiedFlag: false, donateFlag: false },
{ itemID: '600', status: 'active', inventoryFlag: false, certifiedFlag: true, donateFlag: true },
{ itemID: '700', status: 'inactive', inventoryFlag: false, certifiedFlag: true, donateFlag: false }
];
document.getElementById("data").innerText = JSON.stringify(data.filter(o => o.inventoryFlag || o.donateFlag));
<textarea id="data" rows="50" cols="100"></textarea>
I'm trying to find a way to list the filter-by flags in a separate array and then use that in the .filter() somehow to get the same result set as the above code.
For example, here are the flags to use for filtering AND at least one of the values must be true in the object to be included in the final dataset -
const flags = ['inventoryFlag', 'donateFlag'];
As a start, I tried this but it didn't do anything:
const filteredData = data.filter(o => flags.includes(Object.keys(o)));
Inside of the filter, use the some method to detect if any of the property keys of an entry, that are contained in the flags array, have the a value of true.
const data = [
{ itemID: '300', status: 'active', inventoryFlag: true, certifiedFlag: false, donateFlag: true },
{ itemID: '400', status: 'inactive', inventoryFlag: true, certifiedFlag: true, donateFlag: false },
{ itemID: '500', status: 'active', inventoryFlag: false, certifiedFlag: false, donateFlag: false },
{ itemID: '600', status: 'active', inventoryFlag: false, certifiedFlag: true, donateFlag: true },
{ itemID: '700', status: 'inactive', inventoryFlag: false, certifiedFlag: true, donateFlag: false }
];
const flags = ['inventoryFlag', 'donateFlag'];
const result = data.filter(entry =>
flags.some(flag => entry[flag] === true)
);
console.log(result);
I'm trying to sort this array of objects by its boolean properties however, I'm struggling to find a solution with javascripts 'sort' method
I'm trying to sort it, so the top item in the array would be 'offer = true', then 'shortlisted = true', and finally 'rejected = true'.
var toSort = [{
offer: false,
shortlisted: true,
rejected: false,
stage: 2
}, {
offer: false,
shortlisted: false,
rejected: true,
stage: null
}, {
offer: true,
shortlisted: true,
rejected: false,
stage: null
}, {
offer: false,
shortlisted: true,
rejected: false,
stage: 1
}];
This is the final result I would like to achieve
[{
offer: true,
shortlisted: true,
rejected: false,
stage: null
}, {
offer: false,
shortlisted: true,
rejected: false,
stage: 1
}, {
offer: false,
shortlisted: true,
rejected: false,
stage: 2
}, {
offer: false,
shortlisted: false,
rejected: true,
stage: null
}]
What is the best method to sort this array?
You can use sort() like this.
var toSort = [{
offer: false,
shortlisted: true,
rejected: false,
stage: 2
}, {
offer: false,
shortlisted: false,
rejected: true,
stage: null
}, {
offer: true,
shortlisted: true,
rejected: false,
stage: null
}, {
offer: false,
shortlisted: true,
rejected: false,
stage: 1
}];
var result = toSort.sort(function(a, b) {
return b.offer - a.offer ||
b.shortlisted - a.shortlisted ||
b.rejected - a.rejected
})
console.log(result)
One way is to assign a numerical score to each object, setting a higher score for values of higher precedence. For example:
var scoreObj = function(o) {
var score = 0;
if(o.offer) {
score+=100;
}
if(o.shortlisted) {
score+=10;
}
if(o.rejected) {
score+=1;
}
return score;
};
var sorted = toSort.sort(function(a,b){
return scoreObj(b) - scoreObj(a);
});
A simple way :
toSort.sort(function(a, b){
var numberA = a.offer * 5 + a.shortlisted * 3 + a.rejected;
var numberB = b.offer * 5 + b.shortlisted * 3 + b.rejected;
return numberA < numberB
});
Why this works :
1) we can treat boolean as 0 or 1, so if a.offer is true we are adding 5 to numberA, if not 0
2) If offer property is true, even if all other are true, offer will still appear first (because 5 > 1 + 3 = 4)
For more than 3 properties : This way we give a priority to the boolean properties you want first by giving it a numeric value that is greater than the sum of all the less priority properties