我有一个菜单,用户必须从每一行中 Select 一个选项.

-oh my 天.

Menu mockup

此菜单以如下所示的数据表示:

menu = [
  [41, 36, 573, 572],
  [47, 96, 79],
  [480, 479]
]

行数是可变的,每个行中的选项数也是可变的.代表每个选项的数字始终是唯一的.

问题是,并不是每种组合都是有效的.我有一个"允许"组合的列表,如下所示:

variants = [
  [36, 47, 480],
  [41, 96, 480],
  [41, 79, 479],
  [41, 47, 479],
  [572, 47, 479],
  [573, 47, 479],
]

我可以访问随着 Select 的每个选项而增长的数组:

options = []
options = [41]
options = [41, 47]
options = [41, 47, 479]

因为不是每个组合都是有效的,所以必须禁用会导致无效组合的菜单选项,因此给定options数组,我需要一个算法来生成如下数据 struct :

menu_toggles = [
  [true, true, true, true],
  [true, false, true],
  [false, true]
]

然后可以使用此 struct 来启用或禁用实际的菜单选项,就像在样机中一样.

要简化事情,请执行以下操作:

  • 用户必须从第一行中 Select 一个选项,然后从下面 Select 一个选项,依此类推.
  • 如果 Select 了前一行中的某个选项,则会删除在该行之后 Select 的选项.
  • 不能产生有效组合的选项需要禁用,即.menu_toggles中对应的位置必须是false.

实例

使用上面的menuvariants.

未 Select 任何选项

options = []
menu_toggles = [
  [true, true, true, true],
  [false, false, false],
  [false, false]
]

已 Select 一个选项

options = [36]
menu_toggles = [
  [true, true, true, true],
  [true, false, false],
  [false, false]
]

Select 了两个选项

options = [36, 47]
menu_toggles = [
  [true, true, true, true],
  [true, false, false],
  [true, false]
]

Select 了两个选项 (other)

options = [41, 47]
menu_toggles = [
  [true, true, true, true],
  [true, false, false],
  [false, true]
]

当前方法(在 compose 本文时)

我目前的解决方案如下所示:

const available_variants = variants
  .filter(v => {
    if (!v) return false;
    if (!options.every((o, i) => o === v[i])) return false;
    return true;
  });

const menu_toggles = [
  ...menu
    .slice(0, options.length)
      .map(l => l
        .map(() => true)),

  ...menu
    .slice(options.length)
      .map((z, i) => z
        .map((value, j) => available_variants
          .some(v => v[i + options.length] === value)))
];

在本例中,我首先列出了一系列有意义的组合,以便"下一行" Select ,但显然,这只会禁用从该行向下的菜单选项.

推荐答案

下面的代码提供了预期的行为.

const menu_toggles = menu
  .map((row, i) => {
    // This filters `variants` down to options
    // that matter specifically for this `row`
    const available_variants = variants
      .filter(variant => options
        .slice(0, i)
        .every((o, i) => o === variant[i]));
  
    return row
      .map(option => {
        // Disable options in next rows
        if (i > options.length) return false;

        // Enable option if it exists in filtered possible variants
        if (available_variants.some(v => v[i] === option)) return true;

        // Default to disabled
        return false;
      });
  });

Javascript相关问答推荐

Python类实现的JavaScript吊坠是什么样子的?

带对角线分隔符的图像滑动器

用相器进行向内碰撞检测

RxJS setTimeout操作符等效

使用TMS Web Core中的HTML模板中的参数调用过程

警告!合同执行期间遇到错误[执行已恢复](Base Layer 2)

网页自检测外部元素无法加载

如何找出摆线表面上y与x相交的地方?

加载背景图像时同步旋转不显示的问题

使用js构造一个html<;ath&>元素并不能使其正确呈现

搜索功能不是在分页的每一页上进行搜索

回溯替代方式

有效路径同时显示有效路径组件和不存在的路径组件

无法读取未定义的属性(正在读取合并)-react RTK

为列表中的项目设置动画

使用Reaction窗体挂钩注册日历组件

使用可配置项目创建网格

如何在Reaction中清除输入字段

递增/递减按钮React.js/Redux

在Puppeteer中使用promise进行日志(log)记录时出现TargetCloseError