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

rpppsulh  于 2023-05-21  发布在  Java
关注(0)|答案(5)|浏览(140)

我需要创建一个函数,以便返回最宽牧场的起始和结束索引以及宽度。
它需要以这个特定的顺序返回一个数组。
[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]。感觉解决方案很简单,但我无法掌握它,我所有的其他尝试都导致了当前工作代码的破坏。
我唯一的选择是从头重写吗?

mqxuamgl

mqxuamgl1#

第一个问题是变量greatest被设置为倒数第一个分区,而没有比较哪个分区是最长的。即使第一个分区是最长的,greatest仍然会被下一个数组的长度覆盖--即使它更短。
其次,tillGreatest变量获取比最大值短的数组的长度之和。但这也将包括 * 在 * 最大值之后的数组长度。
另一个问题是,由于拆分,您会丢失对起始索引的跟踪。您尝试使用+= 1+= 2来克服这个问题,但这还不够通用。老实说,分割成分区使这比必要的更困难。
我建议不要进行拆分,而只是迭代landscape字符串的每个字符,并跟踪_current 系列的起始索引,并导出其长度。然后,只要得到的长度大于之前注册的长度,就可以更新答案数组。
下面是它的样子:

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

mmvthczy2#

我打算输入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]
wn9m85ua

wn9m85ua3#

一个可行的方法是使用matchAll,它将匹配这个简单的正则表达式…/_+/g ...下划线字符序列(全局)。
结果数组包含匹配项,其中每个项都具有匹配本身(下划线序列),例如index属性表示匹配的开始位置。
sort匹配项的数组,按照每个项的匹配长度以升序排列,将把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; }
kwvwclae

kwvwclae4#

为了探索实现相同功能的各种方法,我们可以使用String的Regular ExpressionsmatchAll方法。
/_+/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。它有一个很好的,干净的,非常有用的UI。如果你需要使用正则表达式,这个网站是必备的工具。

b1uwtaje

b1uwtaje5#

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

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

相关问题