有没有办法在`jq`中实现数组的分配属性?

时间:2017-10-09 03:49:35

标签: arrays json operators jq cartesian-product

我想将2个数组相乘以产生混合缩减。我将此与使用FOIL方法进行比较,将多项式之间的括号项扩展和分布到代数中的结果表达式中。

我希望避免编写foreach循环,即使它自动适用于任何数组长度,并为我想要创建的每个数组混合执行此操作。

我还想避免通过迭代第一个数组来创建一些结果数组,结合第二个数组中的术语,然后以某种方式在此过滤器段中执行总体合成,最后可能需要flatten指令。这似乎是我需要的太多步骤,并且可以更简洁地表示。可能是*运算符?

我开始认为第二种方法是我需要做的,因为我可能不想'乘以'这些术语,而是在处理剩下的任务时创建一个新的数组或对象。< / p>

我的问题开始听起来像是在问{倩} {@ 1}}如何使用过滤器而只使用数据元素而不是实际foreach循环来输入jq循环?

在我的示例中,我基本上想要使用2个数组,每个数组包含要在状态枚举中使用的一对术语,以创建一个结果数组,允许我遍历4个案例。这类似于计算组合的方式。

有人知道我在说什么吗? :)

3 个答案:

答案 0 :(得分:1)

听起来你对外部产品很感兴趣。在任何情况下,这里都是outer/2的定义,用于形成两个数组的外积:

def outer(a; b): [a[] as $x | b[] as $y | [$x, $y]];

示例:

outer([1,2]; [3,4])

的产率:

 [[[1,3],[1,4]],[[2,3],[2,4]]]

外(A; B; F)

您可能想要使用此变体(例如,类似于R中的外部(A,B,f)):

def outer(a; b; f):
  [a[] as $x | b[] as $y | [$x, $y] | f];

例如:

def times: reduce .[] as $x (1;.*$x);

outer([1,2];[3,4]; times)

产生普通的外部产品:

[[3,4],[6,8]]

答案 1 :(得分:1)

使用多个[]迭代器时形成的隐式笛卡尔积可能会帮助您表达问题。例如,以下过滤器计算a1a2的乘积而没有显式循环:

def a1: [1,2];
def a2: [3,4];  
[ a1[] * a2[] ] | add

给出结果21。使用字符串插值可以更清楚地显示操作。使用上述a1a2

[ "(\(a1[]) * \(a2[]))" ] | join("+")

生成

(1 * 3)+(2 * 3)+(1 * 4)+(2 * 4)

您还可以使用对象构造函数形成对象集合。 E.g。

[ {x:a1[], y:a2[]} ]

产生

[
  { "x": 1, "y": 3 },
  { "x": 1, "y": 4 },
  { "x": 2, "y": 3 },
  { "x": 2, "y": 4 }
]

使用这种方法,您需要决定如何组合对象。

答案 2 :(得分:0)

我刚刚做了一个奇怪的定时早上顿悟,我刚试过并给了我一个可接受的结果。

我看到还有其他答案,我可能会接受其中一个完全基于内容的答案,因为它们似乎更简洁和描述性,尤其是数学和编程背景。我希望我能接受不止一个!

我仍会将我的jq表达式添加到混音中,因为它会显示稍微不同的术语,这可能代表我想要的算法,但之前并不清楚,并且在完整的jq中这样做命令调用:

⋊> ~ jq -cn '["one", "two"] as $num | ["a", "b"] as $let | [($num[] | [.]) + ($let[] | [.])]'                                                                                                       10:01:42
[["one","a"],["two","a"],["one","b"],["two","b"]]