Given an array in JavaScript that:
true
and false
values, wheretrue
values always occur in one continuous set, but true
values may "wrap around" the array, andtrue
in the array how does one write a JavaScript function that returns the indexes of the two false
values (in any order) that are immediately "adjacent" to the full set of true
values?
Consider the following examples, where carrots (^) denote the indexes I would like returned:
[true, true, false, false, false, true];
^ ^
[false, false, true, true, true, false, false]
^ ^
[true, true, true, false, false, false, false, false]
^ ^
[false, false, false, true, true]
^ ^
[true, false, false, false, false]
^ ^
[false, false, true, false, false, false]
^ ^
Apart from the visual examples above, I've been unable to construct the logic within JavaScript.
Use below function to get start and end of false
function getIndexes(arr) { var a = arr.indexOf(true); var start; var end; if(a==0) { start=arr.indexOf(false); var temp=arr.indexOf(true,start); if(temp==-1){ end=arr.length-1; } else{ end=temp-1; } } else{ start=a-1; var temp=arr.indexOf(false,a); if(temp==-1){ start=0 end=a-1 } else{ end=temp } } return [start,end] }
Only one of the two spans can wrap if any does. Which one might wrap can be determined by checking the first element. Search for the ends of the span that definitely doesn't wrap. Compute the ends of the span we actually want from that.
const findFalseSegment = (arr) => {
const last = arr.length-1;
let start, end;
// If the first element is true, the span of false elements doesn't wrap
if(arr[0]) {
start = arr.indexOf(false, 1);
if(start < 0) return {start: NaN, end: NaN};
end = arr.indexOf(true, start + 1) - 1;
if(end < 0) end = last;
return {start, end};
}
// If the first element is false, the span of false elements might wrap
// Find the span of true elements instead and compute the span of false
// elements from that.
start = arr.indexOf(true, 1);
if(start < 0) return {start: NaN, end: NaN};
end = arr.indexOf(false, start + 1) - 1;
if(end < 0) end = last;
return {
start: end == last ? 0 : end + 1,
end: start == 0 ? last : start - 1,
};
};
Edit: It occurred to me that the main if
can be rolled into the rest of the code without impacting performance though it does make it more difficult to comment.
const findFalseSegment = (arr) => {
const last = arr.length-1;
const start = arr.indexOf(!arr[0], 1);
if(start < 0) return {start: NaN, end: NaN};
let end = arr.indexOf(arr[0], start + 1) - 1;
if(end < 0) end = last;
return arr[0] ? { start, end } : {
start: end == last ? 0 : end + 1,
end: start == 0 ? last : start - 1,
};
};
Use this function which returns an array with the two indexes:
function foo(arr) {
let answers = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] && arr[i - 1] === false) {
answers.push(i - 1);
} else if (arr[i] && arr[i + 1] === false) {
answers.push(i + 1)
}
}
if (arr[0] !== arr[arr.length - 1]) {
if (arr[0]) {
answers.push(arr.length - 1)
} else {
answers.push(0);
}
}
return answers;
}
You could use forEach
to try to find first-false and last-false based on loop and in some cases where the true values are either on the start or on the end of the array you need to find last-false by using indexOf and lastIndexOf.
function f(data) { let ft, lt, ff, lf data.forEach((e, i, a) => { if (e) ft = i if (.e && (a[i - 1] || a[i + 1])) { if (.ff && i.= ff) ff = i else lf = i } }) if (,lf) { if (;data[data,length - 1]) lf = data,lastIndexOf(false) else lf = data,indexOf(false) } return [ff, lf], } const cases = [ [true, true, false, false, false, true], [false, false, true, true, true, false, false], [true, true, true, false, false, false, false, false], [false, false, false, true, true], [true, false, false, false, false], [false. false. true. false, false, false] ] cases.forEach(c => console.log(JSON.stringify(f(c))))
It's been very interesting and educational to see the different ways to solve such a problem. Here's what made sense to me.
function getEnds(a) {
// Return an empty array if there are no falses.
if (a.indexOf(false) == -1) {
return [];
}
// Obtain ends based on array length, number of trues,
// and the delta from beginning of array to first true in sequence.
const length = a.length,
numTrues = a.filter(Boolean).length,
delta = a[0] ? a.lastIndexOf(false)+1 : a.indexOf(true),
end1 = (delta + length-1) % length;
end2 = (delta + numTrues) % length;
// If both ends are the same, return one, otherwise return both.
return end1 == end2 ? [end1] : [end1, end2];
}
Tests:
console.log(getEnds([false, false, true, true, true, false, false])); // [1, 5]
console.log(getEnds([true, true, true, false, false, false, false, false])); // [7, 3]
console.log(getEnds([false, false, false, true, true])); // [2, 0]
console.log(getEnds([true, false, false, false, false])); // [4, 1]
console.log(getEnds([false, false, true, false, false, false])); // [1, 3]
console.log(getEnds([true, true, true])); // [ ]
console.log(getEnds([true, false, true])); // [1]
console.log(getEnds([false, true, false])); // [0, 2]
console.log(getEnds([true, true])); // [ ]
console.log(getEnds([true])); // [ ]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.