如何在Javascript中返回数组中的正确位置?

How to return the correct position in an array in Javascript?

提问人:AtomicCow 提问时间:5/21/2023 最后编辑:Peter SeligerAtomicCow 更新时间:5/21/2023 访问量:177

问:

我需要制作一个函数,以便它将返回最宽牧场的起始和结束索引以及宽度。

它需要按此特定顺序返回一个数组。

[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]

我唯一的选择是从头开始重写吗?

JavaScript 字符串 算法 拆分 匹配

评论

0赞 trincot 5/21/2023
你在哪里确保这是......最伟大的?greatest

答:

2赞 trincot 5/21/2023 #1

第一个问题是,变量被设置为最后一个分区,而没有比较哪个分区最长。即使第一个分区是最长的,仍然会被下一个数组的长度覆盖 - 即使它更短。greatestgreatest

其次,变量获取比最大数组短的数组长度之和。但这也将包括排在最大数组之后的数组长度。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]

评论

0赞 AtomicCow 5/21/2023
我脑海中遇到的问题是,由于输出需要是一个数组,而不是像输入那样的字符串,我应该将字符串转换为数组,然后对其进行操作。我很早就使用 .indexOf 和 .lastIndexOf 方法找到了解决方案,并尝试将这些数字存储到数组中,但无法将其清除,并使用 .split 方法尝试将我必须处理的部分从整个字符串减少到较小的元素。显然,这让我感到束手无策。
0赞 Lajos Arpad 5/21/2023
我不认为牧场之间的特征一定是.-
0赞 trincot 5/21/2023
@LajosArpad,同意并更新。谢谢!
1赞 Kinglish 5/21/2023 #2

我打算输入关于变量的 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]

评论

1赞 AtomicCow 5/21/2023
您好,感谢您抽出宝贵时间。我对JS很陌生,所以我不懂很多速记。您能解释一下“数学.max(...(array.map(el => el.length)));”应该工作吗?
0赞 Kinglish 5/21/2023
从中间开始,map 函数获取 ____ 的数组,并使用 Array.map 将其转换为数字数组(字符长度)。当您获取一个数字数组并使用 spread 运算符 (...) 将其放入 Math.max 函数中时,它将返回数组中的最高值
1赞 Peter Seliger 5/21/2023 #3

一种可行的方法是利用 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; }

0赞 Lajos Arpad 5/21/2023 #4

您可以在下面找到一个简单的解决方案,该解决方案遍历输入字符,找到牧场,每当它找到比迄今为止最好的牧场更好的牧场时,它就会成为迄今为止最好的牧场。您可以在字里行间找到详细的解释。

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;
}
0赞 M. Çağlar TUFAN 5/21/2023 #5

只是为了探索实现相同功能的各种方法,我们可以使用 String 的正则表达式matchAll 方法。

/_+/g是在 JavaScript 中定义的正则表达式。为了在 JavaScript 中定义正则表达式,我们以 /(斜杠)字符开头和结尾。然后我们编写这些页岩之间的规则。在这里,我写了至少一个或多个下划线来匹配出现的次数。在结束斜杠之后,我们可以键入一些额外的字符来定义正则表达式的标志;通过在表达式后面键入,我们定义了一个全局表达式。全局标志允许匹配给定字符串的所有匹配项,否则我们只会匹配第一个匹配项。要使用方法,我们需要有一个全局正则表达式。以下代码使用以下功能:_+gmatchAll

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。它有一个漂亮、干净且非常有用的用户界面。如果您需要使用正则表达式,这个网站是一个必备的工具。