从 jsonnet 中的对象数组中删除重复项
Remove duplicates from an array of objects in 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}
]
忽略原来的排序顺序
您可以通过将理解替换为 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)
正如@seh 在 ksonnet channel 中指出的那样,最新的 jsonnet 版本现在允许在 objects.
上使用 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()
header 记录在 jsonnet's std lib implementation。
我有一组对象,我想删除重复项。
我的数组有一个公共字段 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}
]
忽略原来的排序顺序
您可以通过将理解替换为 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)
正如@seh 在 ksonnet channel 中指出的那样,最新的 jsonnet 版本现在允许在 objects.
上使用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()
header 记录在 jsonnet's std lib implementation。