首页 > 解决方案 > 在使用带有 jq 的过滤器时将字符串数组均匀地拆分为子数组

问题描述

鉴于我有以下 json

[
    "/home/test-spa/src/components/modals/super-admin/tests/integration/index.test.tsx",
    "/home/test-spa/src/components/modals/delete-user/tests/index.test.tsx",
    "/home/test-spa/src/components/modals/edit-admin/tests/integration/index.test.tsx",
    "/home/test-spa/src/components/modals/delete-admin/tests/index.test.tsx",
    "/home/test-spa/src/components/modals/add-user/tests/integration/index.test.tsx",
    "/home/test-spa/src/components/modals/add-admin/tests/integration/index.test.tsx",
    "/home/test-spa/src/components/modals/edit-user/tests/index.test.tsx",
    "/home/test-spa/src/components/modals/change-user/tests/index.test.tsx",
    "/home/test-spa/src/other-directory/modals/tests/index.test.ts",
    "/home/test-spa/src/directory/modals/tests/index.test.ts",
]
  1. 我想排除字符串中包含目录其他目录的任何内容
  2. 然后我想将数组拆分为 4 个数组,但我想平均拆分字符串中集成的任何内容,即我不希望将所有集成都放在一个数组中。然后可以在 4 个数组中拆分任何其他字符串。

我想使用 jq 来执行这个过滤器。以下代码允许我将 json 拆分为 4,但不执行上述所需的过滤。

jq -cM '[_nwise(length / 4 | floor)]'

结果,我正在寻找类似以下输出的内容(只要集成测试尽可能均匀地拆分,其他字符串就可以均匀填充,顺序无关紧要)

[
    [
        "/home/test-spa/src/components/modals/super-admin/tests/integration/index.test.tsx",
        "/home/test-spa/src/components/modals/delete-user/tests/index.test.tsx"
    ],
    [
        "/home/test-spa/src/components/modals/edit-admin/tests/integration/index.test.tsx",
        "/home/test-spa/src/components/modals/delete-admin/tests/index.test.tsx"
    ],
    [
        "/home/test-spa/src/components/modals/add-admin/tests/integration/index.test.tsx",
        "/home/test-spa/src/components/modals/edit-user/tests/index.test.tsx"
    ],
    [
        "/home/test-spa/src/components/modals/add-user/tests/integration/index.test.tsx",
        "/home/test-spa/src/components/modals/change-user/tests/index.test.tsx"
    ]
]

标签: arraysjsonselectjqpartition

解决方案


如果桶的数量是预先确定的

这是一个通用的“循环”函数,编写后可以有效地执行“has”和“has not”字符串的分配(即,不连接任何数组):

# s is a stream, $n a predetermined number of buckets
def roundrobin(s; $n):
   reduce s as $s ({n: 0, a: []}; .a[.n % $n] += [$s] | .n+=1) | .a;
# First exclude the unwanted elements:
  map(select(test("(other-)?directory")|not))
# Perform the required round-robin:
  | roundrobin( (.[] | select(index("integration"))),
                (.[] | select(index("integration")|not));  4)

如果桶数是数据驱动的

如果桶的数量应该取决于指定字符串的出现次数,那么使用上面定义的roundrobin过滤器,一个合理有效的解决方案可以写成如下:

# First exclude the unwanted elements:
  map(select(test("(other-)?directory")|not))
# Form an array of the strings with the specified substring
  | map(select(index("integration"))) as $has
# Perform the required round-robin:
  | roundrobin( $has[], ((.-$has)[]); $has|length)

推荐阅读