从jsonnet中的对象数组中删除重复项

时间:2018-11-27 21:26:45

标签: jsonnet

我有一个对象数组,我想删除重复项。 我的数组有一个公共字段name,我想将其用于重复数据删除。

我正在尝试将数组转换为地图,然后从地图转换回数组,但是地图转换给我一个错误duplicate field name: "a"

local arr = [ 
    { "name": "a", "value": 1234},
    { "name": "b", "value": 555},
    { "name": "c", "value": 0}, 
    { "name": "a", "value": 1234} 
];
local map = { [x.name] : x  for x in arr };

所需的输出:

[ 
      { "name": "a", "value": 1234},
      { "name": "b", "value": 555}, 
      { "name": "c", "value": 0} 
]

2 个答案:

答案 0 :(得分:1)

忽略原始排序顺序

您可以通过用std.foldl()代替理解来实现它,请注意排序问题:

local arr = [
  { name: "a", value: 4321 },
  { name: "b", value: 555 },
  { name: "c", value: 0 },
  { name: "a", value: 1234 },
];

// Use foldl to iterate from array, can't use comprehension because of dup fields
local map = std.foldl(function(x, y) x { [y.name]: y }, arr, {});

// Re-convert map to array, note that it'll not respect original order
// but fields' (ie 'name' key)
[ map[x] for x in std.objectFields(map)]

保留原始排序顺序

如果需要在输出数组中保留原始排序顺序,则可以添加一个_idx字段以在最后一个sort()中使用:

local arr = [
  { name: "a", value: 4321 },
  { name: "b", value: 555 },
  { name: "c", value: 0 },
  { name: "a", value: 1234 },
];

// Overload array elements with there index (`_idx` field)
local idxArray = std.mapWithIndex(function(i, x) x { _idx:: i }, arr);

// Use foldl to iterate from array, can't use comprehension because of dup fields
local map = std.foldl(function(x, y) x { [y.name]: y }, idxArray, {});

// Re-convert map to array, it'll keep original order via added _idx field
std.sort([map[x] for x in std.objectFields(map)], function(e) e._idx)

答案 1 :(得分:1)

正如@seh在ksonnet channel中指出的那样,最新的jsonnet版本现在允许在对象上使用std.set()

 local arr = [
    { name: "a", value: 1234 },
    { name: "b", value: 555 },
    { name: "c", value: 0 },
    { name: "a", value: 1234 },
  ];
 std.set(arr, function(o) o.name)

std.set()标头记录在jsonnet's std lib implementation中。