将值压入数组会产生未定义的变量,但可在函数内部使用

时间:2018-11-20 11:40:35

标签: javascript arrays

我正在尝试仅使用'appearMost'数组中的'indexes'变量的索引将'eachNumber'数组中的值压入,但由于某种原因,它会返回一个带有未定义值的数组:

var indexes = [1,2];
var appearMost = [];
var eachNumber = [4, 7, 9, 8];

indexes.map(function(c) { appearMost.push(eachNumber[c]) }); // should return [7,9]

appearMost的结果应为[7,9]。

奇怪,因为我构建了一个函数,该函数返回在数组中出现频率最高的数字,而该数组依赖于上面似乎无效的行。例如:

mostAppearing([5,5,2,2,1]); // correctly returns 5
mostAppearing([3,4,1,6,10]); // correctly returns -1
mostAppearing([4,7,7,7,9,9,8]); // correctly returns 7
mostAppearing([4,7,7,9,7,9,9,8]); // correctly returns 9

该函数具有代码:

function mostAppearing(arr) { // e.g. var arr = [4,7,7,9,7,9,9,8];

var eachNumber = Array.from(new Set(arr)); // [4, 7, 9, 8];

if (arr.length == eachNumber.length) {
    return -1;
} else {
    var counts = eachNumber.map(function(c){ return arr.filter(function(el){ return el==c }).length }); // [1, 3, 3, 1];
    var maxVolume = Math.max(...counts); // 3
    var volVolume = counts.filter((c) => c == maxVolume).length; // 2

    if (volVolume == 1) {
        return arr[maxVolume];
    } else {
        var indexes = counts.reduce((a, c, i) => (c === maxVolume) ? a.concat(i) : a, []); // [1,2]
        var appearMost = [];
        indexes.map(function(c) { appearMost.push(eachNumber[c]) }); // relies on this line
        return Math.max(...appearMost);
    }
}

}

谁能解释(1)为什么未定义的值而不是[7,9],以及(2)我的函数如何正常工作?它应该失败。感谢您的帮助。

3 个答案:

答案 0 :(得分:3)

appearMost的值已正确更新。

var indexes = [1,2];
var appearMost = [];
var eachNumber = [4, 7, 9, 8];

indexes.map(function(c) { appearMost.push(eachNumber[c]) })
console.log(appearMost)

我相信您期望map函数的返回值为7,9而不是appearMost内部的值。 由于您未在函数内使用return,因此映射本身不会返回值。 更好的做法是使用map函数的返回数组,而不是对现有的数组进行变异:

appearMost = indexes.map(function(c) { return eachNumber[c] })

答案 1 :(得分:1)

按如下所示更新代码,您将获得所需的结果。在这里count作为对象{ data: d, count: d.length }拥有价值。那么max将保留最大重复值计数。然后过滤counts对象以获得最大重复值,并仅选择data映射到appearMost对象中。从appearMost返回的最大值。

function mostAppearing(arr) { // e.g. var arr = [4,7,7,9,7,9,9,8];
  var eachNumber = Array.from(new Set(arr)); // [4, 7, 9, 8];

  if (arr.length == eachNumber.length) {
    return -1;
  } else {
    var counts = eachNumber.map(function(c) {
      var d = arr.filter(el => el == c);
      return { data: d, count: d.length }
    });

    var max = Math.max(...counts.map(x => x.count));
    var appearMost = counts.filter(c => c.count == max).map(x => x.data[0]);

    return Math.max(...appearMost);
  }
}

console.log(mostAppearing([5,5,2,2,1])); // correctly returns 5
console.log(mostAppearing([3,4,1,6,10])); // correctly returns -1
console.log(mostAppearing([4,7,7,7,9,9,8])); // correctly returns 7
console.log(mostAppearing([4,7,7,9,7,9,9,8])); // correctly returns 9

答案 2 :(得分:0)

为每个项目过滤整个数组可能不是最有效的方法。

您可以通过简化操作遍历数组,创建一个Map,将数组项作为键,并将其出现的值作为值。

然后再次减少它,以获取最多的和最高的数字。我把空数组的保护和所有数字的边缘情况放在单独的函数中只出现一次(两种情况都返回-1):

const highestMostAppearing = (arr) =>
  [
    ...arr
      .reduce(
        (result, number) =>
          result.set(number, (result.get(number) || 0) + 1),
        new Map(),
      )
      .entries(),//Map where key is the number and value is the amount of time it occurs
  ].reduce(//this will error with empty array but mostAppearing will guard for that
    //result is highestNumber and mostAppeared so far
    //  item is the number and how many times it appeared
    ([highestNumber, mostAppeared], [number, appears]) =>
      appears > mostAppeared//current item appeared more often than the most appeared so far
        ? [number, appears]//return current number and how many times it appeared
        //next line checks if current number appeared the same times as highest so far
        //  and checks if current number is higher than the highest appeared number
        : appears === mostAppeared && highestNumber < number
          ? [number, appears]//replace result with current item values
          : [highestNumber, mostAppeared],//return previous result (is most appearing and highest)
  );
const mostAppearing = (arr) => {
  if (arr.length === 0) return -1;//do not call highestMostAppearing with empty array
  const [highest, appearing] = highestMostAppearing(arr);
  if (appearing === 1) return -1;//all numbers appear only once (expensive op here)
  return highest;//return most appearing highest nubmber
};

console.log('=======', mostAppearing([5, 5, 2, 2, 1]));
console.log('=======', mostAppearing([]));