【问题标题】:Convert nested For Loop with .map使用 .map 转换嵌套的 For 循环
【发布时间】:2021-03-02 02:20:44
【问题描述】:

我正在尝试使用 .map() 转换嵌套的 for 循环以使其更具功能性。 我的目标是创建一个简单的卡片组。这是我的工作代码:

 generateDeck() {
    const card = (suit, value) => {
      return suit + value;
    }
    const suits = ["S", "H", "D", "C"];
    const values = ["7", "8", "9", "10", "J", "D", "K", "A"];

    for (let s = 0; s < suits.length; s++) {
      for (let v = 0; v < values.length; v++) {
        this.deck.push(card(suits[s], values[v]))
      }
    }
  }

这是我走了多远:

 generateDeck() {
    const card = (suit, value) => {
      return suit + value;
    }
    const suits = ["S", "H", "D", "C"];
    const values = ["7", "8", "9", "10", "J", "D", "K", "A"];

    let deckNew = suits.map(s => {
      values.forEach(v => { return s + v });
    });

  }

我无法让它工作。您将如何以更简洁、更实用的方式避免嵌套的 for 循环?

谢谢!

【问题讨论】:

  • 在 for-each 中返回东西什么都不做,你可能希望两者都是 map

标签: javascript for-loop ecmascript-6 functional-programming


【解决方案1】:

因此,从函数式编程的角度来看,我认为一个好的方法是尽可能地声明性。您实际上并不需要精心设计此算法,因为“通过从列表中创建每个可能的对而提供的两个列表中的一个新列表”是一个非常常见的操作,为此已经存在很多实现。

const suits = ["♠︎", "♣︎", "♥︎", "♦︎"];
const values = ["7", "8", "9", "10", "J", "D", "K", "A"];
    
const createDeck = R.pipe(
  R.xprod,
  R.map(R.join('')),
);

console.log(
  createDeck(suits, values),
);
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"&gt;&lt;/script&gt;

【讨论】:

    【解决方案2】:

    我认为你应该使用 reduce

    const card = (suit) => (value) => suit + value;
    
    const suits = ['S', 'H', 'D', 'C'];
    const values = ['7', '8', '9', '10', 'J', 'D', 'K', 'A'];
    
    const deck = suits.reduce((prev, suit) => {
        const suitedCard = card(suit);
        return [...prev, ...values.map(suitedCard)];
    }, []);
    
    console.log(deck);

    【讨论】:

      【解决方案3】:

      map 无法做到这一点,因为您必须合并两个数组。但是你也不应该使用flatmap,因为没有值的依赖。你需要的是一个应用函子:

      const arrAp = tf => xs =>
        arrFold(acc => f =>
          arrAppend(acc)
            (arrMap(x => f(x)) (xs)))
              ([])
                (tf);
      
      const arrMap = f => xs =>
        xs.map((x, i) => f(x, i));
      
      const liftA2 = ({map, ap}) => f => tx => ty =>
        ap(map(f) (tx)) (ty);
      
      const arrLiftA2 = liftA2({map: arrMap, ap: arrAp});
      
      const arrFold = f => init => xs => {
        let acc = init;
        
        for (let i = 0; i < xs.length; i++)
          acc = f(acc) (xs[i], i);
      
        return acc;
      };
      
      const arrAppend = xs => ys =>
        xs.concat(ys);
      
      // library code ^^^
      
      const values = ["7", "8", "9", "10", "J", "D", "K", "A"];
      
      const suits = ["S", "H", "D", "C"];
      
      const createDeck = values => suits => [values, suits];
      
      console.log(
        arrLiftA2(createDeck) (values) (suits));

      【讨论】:

        【解决方案4】:

        您可以嵌套地图,这将产生一个二维数组。然后使用flatMap 可以将其转换为一个简单的数组。

        flatMap 扁平化多维数组。例如:

        [[1,2], [3,4]].flatMap(x => x)
        

        将给出 [ 1, 2, 3, 4 ]

        像这样的东西(我没有测试过)

        generateDeck() {
          const card = (suit, value) => {
            return suit + value;
          }
          const suits = ["S", "H", "D", "C"];
          const values = ["7", "8", "9", "10", "J", "D", "K", "A"];
          return suits.flatMap(
            suit => values.map(value => card(suit, value))
          );
        }
        

        【讨论】:

          【解决方案5】:

          您是对的,您可以使用map 使其更具“功能性”。 Map 返回一个新数组,而 forEach 仅循环遍历项目。也可以省略大括号直接返回值。

           generateDeck() {
              const card = (suit, value) => suit + value;
              const suits = ["S", "H", "D", "C"];
              const values = ["7", "8", "9", "10", "J", "D", "K", "A"];
          
              let deckNew = suits.map(s => values.map(v => s + v));
              return deckNew;
           }
          

          【讨论】:

            猜你喜欢
            • 2017-08-08
            • 2012-11-06
            • 1970-01-01
            • 2020-11-26
            • 1970-01-01
            • 1970-01-01
            • 2021-12-11
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多