【问题标题】:How to apply a function to lists of values?如何将函数应用于值列表?
【发布时间】:2021-07-28 07:20:41
【问题描述】:

我有一个二维数组(有点),里面装满了单词。列数因行而异。像这样:

var words = [
  ["foo", "bar"],
  ["end", "start", "finish"],
  ["block"],
  ["prefer", "pretty", "patty", "flock", "freeze"]
]

所以,4 行。我们从每一行中取出一个单词并形成一个 4 单词字符串。我需要打印出所有可能的字符串。我该怎么做?

预期结果:

foo end block prefer
bar end block prefer
foo start block prefer
bar start block prefer
foo finish block prefer
bar finish block prefer
foo end block pretty
...etc

【问题讨论】:

  • 使用相同长度的数组的方式相同。在前面的单词之前切换后面的单词会更容易。
  • 您可能想要搜索“笛卡尔积”。 This answer 可能对您有用,尽管您必须将结果数组 join 放在一起。
  • @ScottSauyet 这看起来很有希望。谢谢!

标签: javascript arrays loops recursion


【解决方案1】:

假设你有以下sentence函数:

const sentence = (a, b, c, d) => `${a} ${b} ${c} ${d}`;

sentence('foo', 'end', 'block', 'prefer');
//=> 'foo end block prefer'

据我了解,您的数组包含每个参数的所有值。

您仍然可以使用上面的函数修改其签名。但是,您确实需要提升它,以便它可以应用于值列表。为此,我将使用:

const sentence = lift((a, b, c, d) => `${a} ${b} ${c} ${d}`);

console.log(

  sentence( ["foo", "bar"]
          , ["end", "start", "finish"]
          , ["block"]
          , ["prefer", "pretty", "patty", "flock", "freeze"]
          )

);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>
<script>const {lift} = R;</script>

【讨论】:

  • lift 很好用。我什至没有考虑过这种方法。我想知道在这种情况下,lift 的最小有用实现是什么。
  • 这可能会回答我之前的评论:const liftArrs = (fn) =&gt; (xs, ...xss) =&gt; xss .length == 0 ? xs .map (fn) : xs .flatMap (x =&gt; liftArrs ((...args) =&gt; fn (x, ...args)) (...xss))。不像 Ramda 的版本那样通用,但很有趣。
【解决方案2】:

您可以将其视为数字的可视化。使用正常的基数 10,每个数字都在 0-10 之间,因此每个位置有 10 个数字,但在您的情况下,第一个有 2 个,第二个有 3 个,第三个只有一个,第四个有 5 个。

所以而不是:

...
[0, 0, 0, 8]
[0, 0, 0, 9]
[0, 0, 1, 0]
[0, 0, 1, 1]
...

你想要:

[0, 0, 0, 0]
[0, 0, 0, 1]
[0, 0, 1, 0]
[0, 0, 1, 1]
[0, 0, 2, 0]
[0, 0, 2, 1]
[1, 0, 0, 0]
[1, 0, 0, 1]
...

所以我将最不重要的符号设置为最后一个元素,以便您可以将其视为一个数字,但如果我要对此进行编程,我可能会选择将数字保留在符号数组的索引中。您知道它溢出的方式是增量是否达到索引的长度。例如。在第三行,最低索引将变为 ["foo", "bar"] 的长度,这意味着它会溢出,您需要继续直到我不再溢出为止。

您已经设法像这样计数,您可以将任何合法数字转换为字符串。例如。 [1, 2, 0, 0](第 6 行的倒数)是 "bar finish block prefer",正如您所见,您只需将数字用作 sybols 数组的同一索引的索引,而符号的实际索引是数字。例如。 2 位于索引 1 中,它的编号为 2,因此您可以使用 words[1][2] 获得它。

祝你好运!

注意:这是一个无代码答案。当问题中没有尝试代码时,我通常没有代码答案。恕我直言,这回答了问题

【讨论】:

    【解决方案3】:

    您可以修改 the answer 我在另一个问题中给出的生成字符串而不是数组,如下所示:

    const cartesian = ([xs, ...xss]) =>
      xs = undefined
        ? []
      : xss.length == 0
        ? xs .map (x => [x])
      : xs .flatMap (x => cartesian (xss) .map (ys => `${x} ${ys}`))
    
    const words = [["foo", "bar"], ["end", "start", "finish"], ["block"], ["prefer", "pretty", "patty", "flock", "freeze"]]
    
    console .log (cartesian (words))
    .as-console-wrapper {max-height: 100% !important; top: 0}

    但我认为保持cartesian 完整并围绕它编写一个包装函数会更好:

    const cartesian = ([xs, ...xss]) =>
      xs = undefined
        ? []
      : xss.length == 0
        ? xs .map (x => [x])
      : xs .flatMap (x => cartesian (xss) .map (ys => [x, ...ys]))
    
    const makePhrases = (wordLists) => 
      cartesian (wordLists) .map (words => words .join (' '))
    
    const words = [["foo", "bar"], ["end", "start", "finish"], ["block"], ["prefer", "pretty", "patty", "flock", "freeze"]]
    
    console .log (makePhrases (words))
    .as-console-wrapper {max-height: 100% !important; top: 0}

    无论如何,适合您问题的搜索词是“笛卡尔积”。

    【讨论】:

      猜你喜欢
      • 2013-07-25
      • 2015-08-25
      • 1970-01-01
      • 2018-06-29
      • 1970-01-01
      • 2017-11-15
      • 2016-08-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多