JS 中的递归挑战将所有可能的数组键组合为 true |错误版本,我附上输入和输出

Posted

技术标签:

【中文标题】JS 中的递归挑战将所有可能的数组键组合为 true |错误版本,我附上输入和输出【英文标题】:Recursive challenge in JS combining all possible array keys in true | false versions, I attach the input and output 【发布时间】:2020-09-18 17:27:00 【问题描述】:

我找到了很多关于数组值之间所有可能组合的解决方案,但我需要一些不同的东西,希望你能支持我。基本上是创建所有可能的对象,将数组键与 true|false 值组合在一起,如下所示:

输入:(应该返回一个由 32 个对象组成的数组,2exp5,5 个键中的两个可能值)

let properties = ['arm','lens','season','food','size'];

输出:

let combinations = [
  "arm": "false","lens": "false","season": "false","food": "false","size": "false"
  "arm": "false","lens": "false","season": "false","food": "false","size": "true"
  "arm": "false","lens": "false","season": "false","food": "true","size": "true"
  "arm": "false","lens": "false","season": "true","food": "true","size": "true"
  "arm": "false","lens": "true","season": "true","food": "true","size": "true"
  "arm": "true","lens": "true","season": "true","food": "true","size": "true"
  "arm": "true","lens": "true","season": "true","food": "false","size": "true"
  "arm": "true","lens": "true","season": "false","food": "false","size": "true"
  and so on...
]

非常感谢!

【问题讨论】:

你尝试了什么? 这不是javascript,但我阅读了这些线程以获取逻辑***.com/questions/5162254/…。 @adiga 已经解决了我的问题。谢谢! 【参考方案1】:

您可以为每个属性使用带有开关的二维矩阵。然后为每个键创建条目并使用Object.fromEntries()创建对象

0 0 0 0 0
0 0 0 0 1
0 0 0 1 0
0 0 0 1 1
etc

数组中总共需要2 ** keys.length 个对象。所以,使用Array.from( 2 ** keys.length )创建它

在map函数中,使用row.toString(2)为当前行创建一个二进制数

添加前导 0 直到字符串为 keys.length long: ("00001")

拆分字符串使其成为一个数组 (["0", "0", "0", "0", "1"])

映射这个数组并为对应的键创建一个条目数组

[["arm","false"],["lens","false"],["season","false"],["food","false"],["size","false"]]

使用Object.fromEntries()从条目数组创建一个对象

这是一个sn-p:

let keys = ['arm', 'lens', 'season', 'food', 'size'];

function combination(keys) 
  return Array.from( length: 2 ** keys.length , (_, row) =>
    Object.fromEntries(
      row.toString(2)
          .padStart(keys.length, 0)
          .split('')
          .map((binary, j) => [keys[j], String(Boolean(+binary))])
    )
  )


console.log(combination(keys))

【讨论】:

你成功了兄弟!你能推荐我学习任何主题或课程,以便能够自己解决这些问题吗?我习惯于从 ws 传统的前端请求数据,但我想提高我解决逻辑问题的技能。非常感谢!【参考方案2】:

我们可以在两个可重用的函数上构建它,如下所示:

const crossproduct = (xss) =>
  xss.reduce ((ps, xs) => ps.reduce ((r, p) => [...r, ...(xs.map (x => [...p, x]))], []), [[]])

const mergeAll = xs => 
  Object.assign (, ...xs)

const combine = (properties, values) => 
  crossproduct (properties.map (p => values.map (v => ([p]: v))))
    .map (mergeAll)


const properties = ['arm', 'lens', 'season', 'food', 'size']
const values = [true, false]

console.log (combine (properties, values))
.as-console-wrapper min-height: 100% !important; top: 0

我们的实用功能是:

crossproduct,它接受一个数组数组并找到它们的笛卡尔积。例如,

crossproduct ([['a', 'b', 'c'], [1, 2], ['x', 'y']])
  //=> [["a", 1, "x"], ["a", 1, "y"], ["a", 2, "x"], ["a", 2, "y"], 
  //    ["b", 1, "x"], ["b", 1, "y"], ["b", 2, "x"], ["b", 2, "y"], 
  //    ["c", 1, "x"], ["c", 1, "y"], ["c", 2, "x"], ["c", 2, "y"]]

mergeAll,它将一组单独的对象组合成一个,如下所示:

mergeAll ([foo: 1, bar: 2, baz: 3])
  //=> foo: 1, bar: 2, baz: 3

这只是Object.assign 的一个薄包装,只需将其应用于数组而不是单个对象。

我们的主要函数combine 首先创建一个数组数组,将各个属性名称与如下值匹配:

  [
    ["arm": true, "arm": false], 
    ["lens": true, "lens": false], 
    ["season": true, "season": false], 
    ["food": true, "food": false], 
    ["size": true, "size": false]
]

这是位properties.map (p => values.map (v => ([p]: v)))。虽然可以将其提取为独立函数,但它似乎没有任何其他用途,因此决定只是代码美学问题。

我们在这个结果上调用crossproduct,得到这个中间格式:

[
  ["arm": true, "lens": true, "season": true, "food": true, "size": true], 
  ["arm": true, "lens": true, "season": true, "food": true, "size": false], 
  ["arm": true, "lens": true, "season": true, "food": false, "size": true], 
  ["arm": true, "lens": true, "season": true, "food": false, "size": false],
  // ... 
  ["arm": false, "lens": false, "season": false, "food": false, "size": false]
]

最后,我们在该数组上调用 .map (mergeAll) 以获得我们的最终格式。

注意,如果mergeAll 真的没有其他用途,它很短,可以很容易地在主函数中内联为.map (xs => Object.assign (, ...xs))。这是我经常使用的一个功能,并且可以在我的实用工具箱中派上用场,所以我个人不会内联它。你可能会有不同的感觉。


请注意这里的基本思想。我们不会尝试一次性解决问题,而是应用一系列转换来获得最终格式。这使我们可以在其中一些步骤中利用可重用的功能。这是一种强大的技术。

【讨论】:

暂时没有过路。令人愉快的分解导致完全可重复使用的部分。这让我想起了构建truth table 所需的许多步骤。我有一个模块,也许我会添加一个作为有趣的答案 非常好的答案和理由,非常感谢!【参考方案3】:

从空数组开始构建,并为键添加 2 种可能性(真/假)。 通过遍历所有键来重复该过程,对于每个键,都取之前的可用结果。

let properties = ["arm", "lens", "season", "food", "size"];

const addTwo = (arr, key) => 
  const result = [];
  ["true", "false"].forEach((val) =>
    arr.forEach((item) => result.push( ...item, [key]: val ))
  );
  return result;
;

const combinations = (arr) => 
  let output = [];
  arr.forEach((key) => (output = addTwo(output, key)));
  return output;
;

console.log(combinations(properties));

【讨论】:

清晰整洁!非常感谢!

以上是关于JS 中的递归挑战将所有可能的数组键组合为 true |错误版本,我附上输入和输出的主要内容,如果未能解决你的问题,请参考以下文章

leecode---40---数组,dfs---求所有的组合为target,有重复数组

将 Array 与 Error 组合为单一类型

php 根据有序键集排序数组。注意:将删除键组中没有相应键的值。

使用递归搜索整数数组中元素的所有组合

非递归实现:从给定的字典中抽出所有相加值SUM的全部组合

Apache Flume - 由多个使用者从单个消息队列中提取数据