【问题标题】:How to count neighboring numbers in an array using Javascript?如何使用Javascript计算数组中的相邻数字?
【发布时间】:2021-03-15 19:15:31
【问题描述】:

我的输入是这样的数组:

[7, 7, 7, 7, 4, 4, 5, 5, 5, 1, 9, 2, 7, 7]

我想将这些数字组合在一起并将它们相加,但要按邻居,而不是按数组中的总数。所以输出将是:

['7:4', '4:2', '5:3', 1, 9, 2, '7:2']

我使用reduce 尝试了几种不同的方法,并且很接近,但使用内置的 Javascript 方法我最终计算了数组中的 ALL,而不是邻居。

const firstArray = [7, 7, 7, 7, 4, 4, 5, 5, 5, 1, 9, 2, 7, 7];
const masterArray = [];

const unique = new Set (numberArray); // Set {7, 4, 5, 1, 9, 2, 7}
unique.forEach(u => {
  masterArray.push(numberArray.filter(e => e === u));
});

console.log(masterArray);

在这里使用 Set 显然是错误的,因为它会获取唯一值并计算它们,但我只想通过邻居来做。所以我想我应该使用reduce,但我遇到了同样的问题。

【问题讨论】:

    标签: javascript arrays sorting arraylist foreach


    【解决方案1】:

    var test = [7, 7, 7, 7, 4, 4, 5, 5, 5, 1, 9, 2, 7, 7];
    
    console.log(
      test.reduce((acc, element) => {
        if (acc.length && acc[acc.length - 1].key == element) {
          acc[acc.length - 1].count++;
        } else {
          acc.push({ key: element, count: 1 });
        }
        
        return acc;
      }, []).map(element => `${element.key}:${element.count}`)
    );

    所以逻辑首先将数字减少到一个数组,跟踪最后一个键和计数。只要密钥相同,计数就会增加。一旦密钥发生变化,就会推送一个新对象以开始下一次运行。在reduce完成后,执行一个map,将key和counts转换成想要的字符串。

    【讨论】:

    • 完美。我在 .map 部分添加了一个检查以单独保留单个数字: element => element.count !== 1 ? ${element.key}:${element.count} : element.key) 并且效果很好。
    【解决方案2】:

    您需要跟踪在持久变量中迭代的最后一个数字,以及最后一个递增数字的出现次数:

    const arr = [7, 7, 7, 7, 4, 4, 5, 5, 5, 1, 9, 2, 7, 7];
    let lastNum = arr[0];
    let count = 0;
    const results = [];
    const doPush = () => {
      results.push(
        count === 1
          ? lastNum
          : `${lastNum}:${count}`
      );
    };
    for (const num of arr) {
      if (num !== lastNum) {
        doPush();
        lastNum = num;
        count = 1;
      } else count++;
    }
    doPush();
    
    console.log(results);

    【讨论】:

    • 这看起来像我会用 C++ 解决它,但这在 javascript 中也更快吗?还有什么时候有一百万个数字? (显示完全缺乏 javascript 经验)
    • 我不知道。一方面,我认为像 JS 这样的高级语言基本上比低级语言慢一些如果低级语言针对性能进行了优化。另一方面,现在的 JS 编译器在优化方面相当不错,因此差异可能不会那么大。与往常一样,为了提高性能,请使用实际输入自行运行一些测试以找出答案。
    【解决方案3】:

    您可以通过查看实际值之前的索引的最后一个值来减少数组。

    const 
        array = [7, 7, 7, 7, 4, 4, 5, 5, 5, 1, 9, 2, 7, 7],
        result = array.reduce((r, value, i, { [i - 1]: last }) => {
            let count = 0;
            if (last === value) count = (+r.pop().toString().split(':')[1] || 0) + 1;
            return [...r, count ? `${value}:${count}`: value];
        }, []);
    
    console.log(result);

    【讨论】:

    • { [i - 1]: last } 这怎么可能?
    • 这是解构,它声明了一个last变量,其中包含第4个参数(包含数组)的i - 1属性的值
    【解决方案4】:

    这里有一个解决方案,使用递归函数将邻居分组,然后Array.prototype.map()用冒号格式化:

    const arr = [7, 7, 7, 7, 4, 4, 5, 5, 5, 1, 9, 2, 7, 7],
      output = (function groupNeighbors([first, ...rest], output = [], last) {
        last === first ? output[output.length - 1].push(first) : output.push([first]); 
        return rest.length ? groupNeighbors(rest, output, first) : output;
      })(arr).map(({ [0]: num, length }) => length > 1 ? [num, length].join(':') : num);
    
    console.log(output);

    由于它使用递归,它在输入数组长度方面受到限制,您可以在此处找到每个浏览器的堆栈大小限制:Browser Javascript Stack size limit

    Array.prototype.reduce() 的变体(略短,无递归,输入长度不受限制):

    const arr = [7, 7, 7, 7, 4, 4, 5, 5, 5, 1, 9, 2, 7, 7],
      output = arr
        .reduce(
          (acc, cur, i, { [i - 1]: last }) =>
            (cur === last ? acc[acc.length - 1].push(cur) : acc.push([cur])) && acc,
          []
        )
        .map(({ [0]: num, length }) => length > 1 ? [num, length].join(':') : num);
    
    console.log(output);

    【讨论】:

      【解决方案5】:

      是的,这里的正确选择是reduce

      const countDuplicatesQuantity = (arr) => {
          const duplicatesObj = arr.reduce((duplicates, item) => {
              duplicates[item] = duplicates[item] ? duplicates[item] + 1 : 1;
      
              return duplicates;
          }, {});
      
          return Object.keys(duplicatesObj).map(
              (key) => `${key}:${duplicatesObj[key]}`,
          );
      };
      

      【讨论】:

        【解决方案6】:

        你想减少,两次怎么样? :)(我不知道我是否在这里做了一些愚蠢的事情。)

        首先reduce找到数组中值变化的地方,第二个使用它来构建新数组。

        const firstArray = [7, 7, 7, 7, 4, 4, 5, 5, 5, 1, 9, 2, 7, 7];
        
        const masterArray = firstArray
          .reduce((acc, v, i, all) => all[i + 1] !== v ? acc.concat(i) : acc, [])
          .reduce(
            (acc, v, i, all) => {
              const range = v - (i === 0 ? -1 : all[i - 1]);
              return acc.concat(range > 1 ? firstArray[v] + ':' + range : firstArray[v]);
            }, []
          );
          
        
        console.log(masterArray);

        【讨论】:

          【解决方案7】:

          使用array.reduce:

          const firstArray = [7, 7, 7, 7, 4, 4, 5, 5, 5, 1, 9, 2, 7, 7];
          var newArray = [];
          var count = 0;
          firstArray.reduce((acc, cur, index) => {
            if (acc == cur) {
              count++;
            }
            if (acc != cur || index+1 == firstArray.length) {
              newArray.push(acc + ":" + count);
              count=1
            }
            return cur;
          })
          console.log(newArray);

          【讨论】:

            【解决方案8】:

            我的方式......我觉得可以“更简单”

            const firstArray = [7, 7, 7, 7, 4, 4, 5, 5, 5, 1, 9, 2, 7, 7];
             
            const result = firstArray.reduceRight((r,v)=>
              {
              let [n,c] = !r.length ? [-v,0] : isNaN(r[0]) ? r[0].split(':') : [r[0],1]
              if (n==v) r[0] = `${n}:${++c}`
              else      r.unshift(v)
              return r
              },[])
              
            console.log( JSON.stringify(result) )
            //  [ "7:4", "4:2", "5:3", 1, 9, 2, "7:2" ]
            .as-console-wrapper { max-height: 100% !important; top: 0; }

            【讨论】:

            • @stonerose036 我觉得可以“更简单”
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-09-02
            • 1970-01-01
            • 2023-03-16
            • 2012-09-18
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多