繁体   English   中英

使用 .map 转换嵌套的 For 循环

[英]Convert nested For Loop with .map

我正在尝试使用 .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 循环?

谢谢!

你不能用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));

您是对的,您可以使用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;
 }

您可以嵌套地图,这将产生一个二维数组。 然后使用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))
  );
}

我认为你应该使用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);

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

 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), );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM