【问题标题】:DataWeave 2.0 how to build dynamically populated accumulator for reduce()DataWeave 2.0 如何为 reduce() 构建动态填充的累加器
【发布时间】:2020-12-10 08:49:44
【问题描述】:

我正在尝试将字符串数组转换为每个成员使用字符串作为键的对象,并将值初始化为 0。(用于字数统计的经典累加器,对吗?)

输入数据的样式如下:

%dw 2.0
output application/dw
var hosts = [
  "t.me",
  "thewholeshebang.com",
  "thegothicparty.com",
  "windowdressing.com",
  "thegothicparty.com"
]

要获得累加器,我需要这种风格的结构:

var histogram_acc = {
    "t.me" : 1, 
    "thewholeshebang.com" : 1, 
    "thegothicparty.com" : 2, 
    "windowdressing.com" : 1
}

我的想法是,这是 reduce() 的一个灌篮案例,对吧?

所以要获得去重的主机列表,我们可以使用这个短语:

hosts distinctBy $

到目前为止很开心。但现在对我来说,它变得邪恶了。

我认为这可能是黄金:

hosts distinctBy $ reduce (ep,acc={}) -> acc ++ {ep: 0}

但问题是这并没有那么好。 reduce() 的 lambda 的第一个参数表示迭代元素,在本例中为端点或地址。 lambda 将新对象附加到累加器。

嗯,这就是我希望它发生的方式,但我得到了这个:

{
  ep: 0,
  ep: 0,
  ep: 0,
  ep: 0
}

我有点需要它做得比这更好。

【问题讨论】:

    标签: reduce dataweave mulesoft


    【解决方案1】:

    场景 1: 对于这种情况,我认为的技巧是您需要用 {}distinctBy ... map 的表达式括起来。

    示例:

    输入:

    %dw 2.0
    var hosts = [
      "t.me",
      "thewholeshebang.com",
      "thegothicparty.com",
      "windowdressing.com",
      "thegothicparty.com"
    ]
    output application/json
    ---
    { // This open bracket will do the trick. 
      (hosts distinctBy $ map {($):0})
    } // See Scenario 2 if you remove or comment this pair bracket
    

    输出:

    {
        "t.me": 0,
        "thewholeshebang.com": 0,
        "thegothicparty.com": 0,
        "windowdressing.com": 0
    }
    

    场景 2:如果您从表达式 {<expression distinctBy..map...} 中删除 {},则输出将是一个数组。

    示例:

    输入:

    %dw 2.0
    var hosts = [
      "t.me",
      "thewholeshebang.com",
      "thegothicparty.com",
      "windowdressing.com",
      "thegothicparty.com"
    ]
    output application/json
    ---
    //{ // This is now commented
      (hosts distinctBy $ map {($):0})
    //} // This is now commented
    

    输出:

    [
        {
          "t.me": 0
        },
        {
          "thewholeshebang.com": 0
        },
        {
          "thegothicparty.com": 0
        },
        {
          "windowdressing.com": 0
        }
    ]
    

    场景3:如果要统计每件商品的总重复次数,可以使用groupBysizeOf

    示例:

    输入:

    %dw 2.0
    var hosts = [
      "t.me",
      "thewholeshebang.com",
      "thegothicparty.com",
      "windowdressing.com",
      "thegothicparty.com"
    ]
    output application/json
    ---
    hosts groupBy $ mapObject (value,key) -> {
        (key): sizeOf(value)
    }
    

    输出:

    {
      "t.me": 1,
      "thewholeshebang.com": 1,
      "thegothicparty.com": 2,
      "windowdressing.com": 1
    }
    

    【讨论】:

    • 好的,第三个例子看起来异常高效。我很想将它与大规模缩减进行比较,看看是否存在性能差异。
    【解决方案2】:

    正如你所说reduce 非常适合这个问题,或者你可以使用对象的“动态元素”功能来“将一组对象扁平化为一个对象”

    %dw 2.0
    output application/dw
    var hosts = [
      "t.me",
      "thewholeshebang.com",
      "thegothicparty.com",
      "windowdressing.com",
      "thegothicparty.com"
    ]
    ---
    {(
        hosts 
            distinctBy $ 
            map (ep) -> {"$ep": 0}
    )}
    

    https://docs.mulesoft.com/mule-runtime/4.3/dataweave-types#dynamic_elements

    【讨论】:

      【解决方案3】:

      有趣的是(但也许只是对我而言),我在写问题时发现了这个问题的答案。希望有人会提出同样的问题,这是我发现的。

      为了在我的示例 (ep) 中将 lambda 参数表示为结构中的键,我必须引用并插入它。

      "$ep"
      

      一旦我这样做了,这是一个快速通道:

      hosts distinctBy $ reduce (ep,acc={}) -> acc ++ {"$ep": 0}
      

      ...当然还有这个:

      {
        "t.me": 0,
        "thewholeshebang.com": 0,
        "thegothicparty.com": 0,
        "windowdressing.com": 0
      }
      

      【讨论】:

      • 再看一遍,我意识到我不需要在这种情况下使用reduce。我想我只是在滚动。看了上面的回复,我意识到这个工作可能应该是 map 而不是 reduce。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-18
      • 2020-12-10
      • 2021-03-26
      • 2021-04-08
      相关资源
      最近更新 更多