【问题标题】:Sort functionally an array based on attribute and group bits of the array together根据数组的属性和组位对数组进行功能排序
【发布时间】:2020-03-17 12:54:33
【问题描述】:

我有这个数组:

const nums = [
 {name: 'a', option: false},
 {name: 'b', option: false},
 {name: 'c', option: false},
 {name: 'd', option: false},
 {name: 'e', option: false},
 {name: 'f', option: true},
 {name: 'g', option: true},
 {name: 'h', option: false},
 {name: 'i', option: true},
 {name: 'j', option: false},
 {name: 'k', option: false},
];

我想重新组织这个数组,以便元素在数组中移动时,具有“false”选项的元素按 4 个元素组分组在一起,但如果有一个元素具有“true”选项,它优先并放在 4 个元素的组之前,除非前面的 4 个元素组是完整的(即它的长度等于 4)。

结果是

const nums = [
 {name: 'a', option: false},
 {name: 'b', option: false},
 {name: 'c', option: false},
 {name: 'd', option: false},
 {name: 'f', option: true},
 {name: 'g', option: true},
 {name: 'i', option: true},
 {name: 'e', option: false},
 {name: 'h', option: false},
 {name: 'j', option: false},
 {name: 'k', option: false},
];

我在命令式风格上取得了成功

let stock = [];
let array2 = [];
for (let i = 0; i < nums.length; i ++){
  if (nums[i].option){
    array2.push(nums[i]);
  }
  else {
    stock.push(nums[i]);
    if(stock.length == 4) {
      array2 = array2.concat(stock);
      stock = [];
    }
  }
}

console.log('array2 is', array2);

到目前为止,一切都很好 我现在想以一种实用的方式来做 这是我的方式:

let stock = [];
const actual = nums.map(
 (acc => val => {
   if (val.option){
     acc.push(val);
   }
   else {
     stock.push(val);
     if (stock.length === 4) {
       acc = acc.concat(stock);
       stock = [];
     }
   }
   return acc;
 })([]))

console.log('actual is, ', actual[actual.length-1]);

虽然它有效,但我认为函数式编程风格可以改进。 你能帮我改进我的代码吗?

注意: 有些人发现这个问题有点不寻常(确实如此)。因此,我将提供更多上下文:

潜在的问题是传统样式类无法解决的 UI 样式问题:我有一个网格容器,其中包含四个网格元素的行(当它们未“打开”时)。

当它被打开时,卡片占据了所有的行并且后面的元素被推回。问题是它不漂亮,因为我有一些行可能只包含一个或两个未打开的元素,直到下一行,打开的卡片占用下一行的所有空间。

所以我们的想法是将四个未打开的元素一组,储存起来直到我有一组四个,然后将它们刷新在一行上。如果我遇到一张打开的卡片,我会先显示这张卡片,然后刷新未打开的元素。

【问题讨论】:

  • 是“真”元素也打算被分组,还是所有“真”元素都存在于一组“假”组中,每组 4 个,意在冒泡在下一组“假”之前? (顺便说一句,这是一个非常奇怪的问题……就要求而言,这很不寻常!)
  • “真正的”元素并不意味着组合在一起
  • 那么这会是一个有效的案例吗? FFTFFTTFTFTT => TFFFFTTTTTFF
  • 是的,没错,这将是一个有效的案例

标签: javascript arrays sorting functional-programming


【解决方案1】:

你可以使用递归。

const bubble = (xxs, acc = []) => {
    if (xxs.length === 0) return acc;
    if (acc.length === 4) return [...acc, ...bubble(xxs)];
    const [x, ...xs] = xxs;
    if (x.option) return [x, ...bubble(xs, acc)];
    return bubble(xs, [...acc, x]);
};

const nums = [
 {name: 'a', option: false},
 {name: 'b', option: false},
 {name: 'c', option: false},
 {name: 'd', option: false},
 {name: 'e', option: false},
 {name: 'f', option: true},
 {name: 'g', option: true},
 {name: 'h', option: false},
 {name: 'i', option: true},
 {name: 'j', option: false},
 {name: 'k', option: false},
];

const result = bubble(nums);

console.log(result);

效率不高,但很实用。

【讨论】:

    【解决方案2】:

    我实际上会采用与您类似的方法, 使用chunk 作为临时值来存储不完整的组。

    const group = (data = [], chunk = [], res = []) => {
      if (!data.length) {
        // input is empty,
        // flush any possible incomplete chunk
        // and return result
        return [...res, ...chunk];
      }
    
      const [head, ...tail] = data;
      const next = (...xs) => group(tail, ...xs);
      
      if (head.option) {
        // head.option is true, so you can 
        // safely put it in tail position
        return next(chunk, [...res, head]);
      }
      
      if (chunk.length < 4) {
        // chunk is not-complete, so keep accumulating
        return next([...chunk, head], res);
      }
    
      // chunk is complete, append it to the rest 
      // and create a new one with the current value
      return next([head], [...res, ...chunk]);
    };
    
    const data = [
     {name: 'a', option: false},
     {name: 'b', option: false},
     {name: 'c', option: false},
     {name: 'd', option: false},
     {name: 'e', option: false},
     {name: 'f', option: true},
     {name: 'g', option: true},
     {name: 'h', option: false},
     {name: 'i', option: true},
     {name: 'j', option: false},
     {name: 'k', option: false},
    ];
    
    console.log('result is', group(data));

    这里需要递归,它们的状态是:

    1. 空输入(基本情况)
    2. chunk, (res + head)
    3. (chunk + head), res
    4. head, (res + chunk)

    【讨论】:

      猜你喜欢
      • 2020-09-22
      • 2014-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多