提问人:AtomicCow 提问时间:5/21/2023 最后编辑:Peter SeligerAtomicCow 更新时间:5/21/2023 访问量:177
如何在Javascript中返回数组中的正确位置?
How to return the correct position in an array in Javascript?
问:
我需要制作一个函数,以便它将返回最宽牧场的起始和结束索引以及宽度。
它需要按此特定顺序返回一个数组。
[length, starting_index, ending_index]
例如,对于 ,返回值应为 。"_-___-__-____-______-_"
[6, 14, 19]
如果有多个长度相同的牧场,则返回牧场在数组末尾的位置。
例如,对于 ,返回值应为 。"_-___-__-___-"
[3, 9, 11]
如果最宽的牧场长度为 0,例如 ,则所有值都返回 0。"---"
[0, 0, 0]
var widestPasture = function (landscape) {
// Implement your code below
let array = landscape.split("-");
let greatest;
let tillGreatest = 0;
let endIndex;
let answer = [];
for (let i = 0; i < array.length; i++) {
if (array[i + 1] !== undefined) {
greatest = array[i].length;
}
}
for (let i = 0; i < array.length; i++) {
if (array[i].length < greatest) {
tillGreatest += array[i].length;
}
}
let startIndex = tillGreatest += 1;
tillGreatest += 2;
endIndex = tillGreatest + greatest -1;
answer = [greatest, tillGreatest, endIndex];
return answer;
};
console.log(widestPasture("_-___-__-____-______-_"));
// -> [6, 14, 19]
console.log(widestPasture("_-___-__-___-"));
// -> [3, 9, 11]
我遇到的问题是弄清楚如何输出.目前,第二个输出是 。感觉解决方案很简单,但我无法掌握它,我所有其他尝试的结果都是破坏了当前工作的代码。[3, 9, 11]
[3, 6, 8]
我唯一的选择是从头开始重写吗?
答:
第一个问题是,变量被设置为最后一个分区,而没有比较哪个分区最长。即使第一个分区是最长的,仍然会被下一个数组的长度覆盖 - 即使它更短。greatest
greatest
其次,变量获取比最大数组短的数组长度之和。但这也将包括排在最大数组之后的数组长度。tillGreatest
另一个问题是,由于拆分,您会忘记起始索引。你试图用 和 来克服这个问题,但这还不够通用。老实说,拆分为分区使这变得比必要的更难。+= 1
+= 2
我建议不要进行拆分,而只是访问字符串的每个字符并跟踪当前序列的起始索引,并推导出其长度。然后,只要您获得的长度大于之前注册的长度,您就可以更新答案数组。landscape
_
这是它的样子:
var widestPasture = function (landscape) {
let answer = [0, 0, 0];
for (let i = 0, start = 0; i < landscape.length; i++) {
if (landscape[i] != "_") {
start = i + 1;
} else if (i + 1 - start >= answer[0]) {
answer = [i + 1 - start, start, i];
}
}
return answer;
};
console.log(widestPasture("_-___-__-____-______-_"));
// -> [6, 14, 19]
console.log(widestPasture("_-___-__-___-"));
// -> [3, 9, 11]
评论
-
我打算输入关于变量的 Trincots 解释,所以我不会在这里重复,他们的解决方案很棒。这是一个替代解决方案,因此您可以看到不同的方法greatest
var widestPasture = function (landscape) {
let array = landscape.split("-");
let longest = Math.max(...(array.map(el => el.length)));
let pos = array.lastIndexOf("_".repeat(longest));
//reconstruct
let c =0, firstIndex=0;
while (c<pos) {
firstIndex += array[c].length +1;
c++;
}
let answer = [longest, firstIndex, firstIndex+longest-1];
return answer;
};
console.log(widestPasture("_-___-__-____-______-_"));
// -> [6, 14, 19]
console.log(widestPasture("_-___-__-___-"));
// -> [3, 9, 11]
评论
一种可行的方法是利用 matchAll
,它将匹配这个简单的正则表达式......一系列下划线字符(全局)。/_+/g
result 数组包含匹配项,其中每个项都具有匹配本身(下划线序列)和例如指示匹配起始位置的属性。index
按每个项目的匹配长度按升序对匹配项的数组进行排序
,会将 OP 感兴趣的匹配结果作为排序数组的最后一项。从这个项目中,可以创建/组装 OP 正在寻找的结果数组。
function getLastValidMatchingPastureData(value) {
const lastValidPastureMatch = [...String(value).matchAll(/_+/g)]
// sort each matching pasture data item ascending by `length`.
.sort(([a], [b]) => a.length - b.length)
// access/get the last matching item (the last longest item).
.at(-1);
return [ // assemble the data of OP's interest.
lastValidPastureMatch[0].length,
lastValidPastureMatch.index,
lastValidPastureMatch.index + lastValidPastureMatch[0].length - 1,
];
}
console.log( // [3, 9, 11]
'"_-___-__-___-" ... ',
getLastValidMatchingPastureData("_-___-__-___-"),
);
console.log( // [6, 14, 19]
'"_-___-__-____-______-_" ... ',
getLastValidMatchingPastureData("_-___-__-____-______-_"),
);
console.log( // [6, 21, 26]
'"_-___-__-______-____-______-_" ... ',
getLastValidMatchingPastureData("_-___-__-______-____-______-_"),
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
您可以在下面找到一个简单的解决方案,该解决方案遍历输入字符,找到牧场,每当它找到比迄今为止最好的牧场更好的牧场时,它就会成为迄今为止最好的牧场。您可以在字里行间找到详细的解释。
function widestPasture(input) {
//At the very start we do not have a solution yet, do we default bestSofar to undefined
let bestSofar = undefined;
//lastStartIndex being negative means we are currently not inside a pasture
let lastStartIndex = -1;
//we loop the indexes of the string
for (let i = 0; i < input.length; i++) {
//we check whether the current character is outside of a pasture
if (input[i] !== '_') {
//if so, and we were in a pasture just before, then we found the end of
//the current pasture at the previous index of i - 1
if (lastStartIndex >= 0) {
//we create a solution array in order to compare to the best so far
let currentPasture = [i - lastStartIndex, lastStartIndex, i - 1];
//if we did not have a best earlier, or the best so far is not
//strictly worse than our current solution, then we replace bestSofar
//with the currentPasture
if ((!bestSofar) || (bestSofar[0] <= currentPasture[0])) bestSofar = currentPasture;
//since we have left the pasture, we mark lastStartIndex with a negative
//value so we will be aware that we are not inside a pasture
lastStartIndex = -1;
}
//the else here means that the character is '_', so that we are inside a pasture
} else if (lastStartIndex < 0) lastStartIndex = i;
}
//After the loop we check whether we were inside a pasture at the last character
//to cover (literally) edge-cases
if (lastStartIndex >= 0) {
//We create the currentPasture array
let currentPasture = [input.length - lastStartIndex, lastStartIndex, input.length - 1];
//and compare it with the best so far and if it's better, then it will become
//the new best
if ((!bestSofar) || (bestSofar[0] <= currentPasture[0])) bestSofar = currentPasture;
}
return bestSofar;
}
console.log(widestPasture("_-___-__-____-______-_"));
// -> [6, 14, 19]
console.log(widestPasture("_-___-__-___-"));
// -> [3, 9, 11]
console.log(widestPasture("_-__-___"));
// -> [3, 5, 7]
这就是没有注释的解决方案的样子
function widestPasture(input) {
let bestSofar = undefined;
let lastStartIndex = -1;
for (let i = 0; i < input.length; i++) {
if (input[i] !== '_') {
if (lastStartIndex >= 0) {
let currentPasture = [i - lastStartIndex, lastStartIndex, i - 1];
if ((!bestSofar) || (bestSofar[0] <= currentPasture[0])) bestSofar = currentPasture;
lastStartIndex = -1;
}
} else if (lastStartIndex < 0) lastStartIndex = i;
}
if (lastStartIndex >= 0) {
let currentPasture = [input.length - lastStartIndex, lastStartIndex, input.length - 1];
if ((!bestSofar) || (bestSofar[0] <= currentPasture[0])) bestSofar = currentPasture;
}
return bestSofar;
}
只是为了探索实现相同功能的各种方法,我们可以使用 String 的正则表达式和 matchAll 方法。
/_+/g
是在 JavaScript 中定义的正则表达式。为了在 JavaScript 中定义正则表达式,我们以 /(斜杠)字符开头和结尾。然后我们编写这些页岩之间的规则。在这里,我写了至少一个或多个下划线来匹配出现的次数。在结束斜杠之后,我们可以键入一些额外的字符来定义正则表达式的标志;通过在表达式后面键入,我们定义了一个全局表达式。全局标志允许匹配给定字符串的所有匹配项,否则我们只会匹配第一个匹配项。要使用方法,我们需要有一个全局正则表达式。以下代码使用以下功能:_+
g
matchAll
function widestPasture(landscape) {
const expression = /_+/g;
var result = [0, 0, 0];
var allMatches = landscape.matchAll(expression);
var currentMatch = allMatches.next();
while(!currentMatch.done) {
let { 0: value, index: tillGreatest } = currentMatch.value;
if(value.length >= result[0]) {
result[0] = value.length;
result[1] = tillGreatest;
result[2] = tillGreatest+(value.length-1)
}
currentMatch = allMatches.next();
}
return result;
}
console.log(widestPasture("_-___-__-____-______-_"));
// Output: [6, 14, 19]
console.log(widestPasture("_-___-__-___-"));
// Output: [3, 9, 11]
console.log(widestPasture("---"));
// Output: [0, 0, 0]
旁注:要轻松测试正则表达式并探索有关它们的更多信息,您可以访问 RegExr。它有一个漂亮、干净且非常有用的用户界面。如果您需要使用正则表达式,这个网站是一个必备的工具。
评论
greatest