【问题标题】:How to remove *some* items from array when there is repetition? (Lodash/Underscore preferred)重复时如何从数组中删除*一些*项? (首选 Lodash/下划线)
【发布时间】:2017-08-16 03:51:04
【问题描述】:

我正在尝试编写一个函数,从 6 个骰子的数组中过滤掉三元组。有没有使用 Lodash 或 Underscore 的简单方法?

noTriplets([1,1,1,3,3,5]) // = [3,3,5]
noTriplets([1,1,1,1,3,5]) // = [1,3,5]
noTriplets([1,1,1,1,1,5]) // = [1,1,5]
noTriplets([1,1,1,5,5,5]) // = []
noTriplets([1,1,1,1,1,1]) // = []

【问题讨论】:

  • 这取决于你认为什么容易......到目前为止你做了什么?
  • 嗨,乔 - 你能确认一下你在寻找什么条件吗?在示例 3 中,您在数组中返回两个 1s,但在示例 4 和 5 中,您没有返回任何内容。条件是,每次有一个数字的三个,去掉那个三个,但是如果有四个,你想返回1。如果有6,你想返回none,因为你去掉了3和3。这样对吗?
  • @ChristopherMesser 你是对的。我想删除数组中的所有三元组。
  • @Teemu 请参阅下面的答案。它对我来说看起来有点脏,因为它会改变原始数组。我想一个临时变量可以解决问题,但我不喜欢将三元组创建为一个单独的数组,然后遍历它。

标签: javascript node.js underscore.js lodash


【解决方案1】:

它有点粗糙和肮脏,但它不需要你提前知道你的三胞胎。在noTriplets() 中——我创建了一个快速的 hashMap,然后循环遍历该对象。循环逻辑处理三元组。

const arrayTestOne = [1,1,1,3,3,5];
const arrayTestTwo = [1,1,1,1,3,3,5];
const arrayTestThree = [1,1,1,3,3,3];
const arrayTestFour = [1,1,1,1,3,3,3,5,5,5,5,5,5,5,5,5,5,5,5,7,7];

const hashMap = (array) => array.reduce((allNums, num) => {
  if (num in allNums) {
    allNums[num]++
  }
  else {
	allNums[num] = 1
  }
  return allNums
}, {})

function noTriplets(arr) {
  let newArr = [];
  let obj = hashMap(arr);
  for (var key in obj) {
    for (let i=0; i < obj[key] % 3; i++) {
      newArr.push(key)
    }
  }
  console.log(newArr)
}

noTriplets(arrayTestOne)
noTriplets(arrayTestTwo)
noTriplets(arrayTestThree)
noTriplets(arrayTestFour)

【讨论】:

  • 这是我一直在寻找的方法,除了使用 lodash 可以缩短实现时间。这是我的看法:function noTriplets(arr) { var hashMap = _.countBy(arr); return _.flatten(_.keys(hashMap).map(n =&gt; Array(hashMap[n]%3).fill(n))) }
【解决方案2】:

您可以对每个项目使用计数并计算要忽略的项目数。

function noTriplets(array) {
    var hash = {};

    array.forEach(function (a) {
        hash[a] = hash[a] || { count: 0 };
        hash[a].ignore = Math.floor(++hash[a].count / 3) * 3;
    });

    return array.filter(function (a, i) {
        return --hash[a].ignore < 0;
    });
}

console.log(noTriplets([1, 1, 1, 3, 3, 5])); // [3, 3, 5]
console.log(noTriplets([1, 1, 1, 1, 3, 5])); // [1, 3, 5]
console.log(noTriplets([1, 1, 1, 1, 1, 5])); // [1, 1, 5]
console.log(noTriplets([1, 1, 1, 5, 5, 5])); // []
console.log(noTriplets([1, 1, 1, 1, 1, 1])); // []
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案3】:

    您可以使用一个对象来记录值,然后使用前一个对象生成一个新数组。

    function noTriplets(arr){
      var tripletCount = arr.reduce((dice,value) => {
        dice[value] = dice[value] || { count : 0 };
        dice[value].count = (dice[value].count + 1) % 3;
        return dice;
      },{});
      
      return Object.keys(tripletCount).reduce((arr,key) => {
        return arr.concat(new Array(tripletCount[key].count).fill(key));
      },[]);
    }
    
    console.log(noTriplets([1, 1, 1, 3, 3, 5])); // [3, 3, 5]
    console.log(noTriplets([1, 1, 1, 1, 3, 5])); // [1, 3, 5]
    console.log(noTriplets([1, 1, 1, 1, 1, 5])); // [1, 1, 5]
    console.log(noTriplets([1, 1, 1, 5, 5, 5])); // []
    console.log(noTriplets([1, 1, 1, 1, 1, 1])); // []

    【讨论】:

      【解决方案4】:

      我的纯 JS 通用解决方案。您可以指定应删除多少重复项。比如这里创建了noDoublesnoTripletsnoQuadruples方法。

      function isArrayWithIdenticalElements(array) {
        return array.length > 1 && !!array.reduce(function(a, b){ return (a === b) ? a : NaN; });
      }
      
      function noRepetition(numberOfRepetition, array) {
        var sliceLength = numberOfRepetition - 1;
        var pointer = sliceLength;
        var element = array[pointer];
      
        while (element) {
          if (isArrayWithIdenticalElements(array.slice(pointer - sliceLength, pointer + 1))) {
            array.splice(pointer - sliceLength, numberOfRepetition);
      
            pointer = pointer - sliceLength;
            element = array[pointer];
          } else {
            pointer = pointer + 1;
            element = array[pointer];
          }
        }
      
        return array;
      }
      
      var noDoubles = noRepetition.bind(null, 2);
      var noTriplets = noRepetition.bind(null, 3);
      var noQuadruples = noRepetition.bind(null, 4);
      
      console.log('noTriplets([1,1,1,3,3,5] ==> ', noTriplets([1,1,1,3,3,5])); // = [3,3,5]
      console.log('noTriplets([1,1,1,1,3,5] ==> ', noTriplets([1,1,1,1,3,5])); // = [1,3,5]
      console.log('noTriplets([1,1,1,1,1,5] ==> ', noTriplets([1,1,1,1,1,5])); // = [1,1,5]
      console.log('noTriplets([1,1,1,5,5,5] ==> ', noTriplets([1,1,1,5,5,5])); // = []
      console.log('noTriplets([1,1,1,1,1,1] ==> ', noTriplets([1,1,1,1,1,1])); // = []
      
      console.log('noQuadruples([1,1,1,3,3,5] ==> ', noQuadruples([1,1,1,3,3,5])); // = [1,1,1,3,3,5]
      console.log('noQuadruples([1,1,1,1,3,5] ==> ', noQuadruples([1,1,1,1,3,5])); // = [3,5]
      
      console.log('noDoubles([1,1,1,5,5,5] ==> ', noDoubles([1,1,1,5,5,5])); // = [1,5]

      【讨论】:

        【解决方案5】:

        很好的答案!在阅读了每个人的答案,尤其是 Christopher Messer 的答案后,我想出了一个基于 lodash 的版本:

        function noTriplets(arr) {
          var hashMap = _.countBy(arr)
          var filler = n => Array(hashMap[n] % 3).fill(n)
          return _.flatten(_.keys(hashMap).map(filler))
        }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-10-22
          • 2015-05-05
          • 2023-03-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多