我将以下数据结构作为输入
我想对数据进行特殊分组,而不丢失任何数据
const input =
[
{
Id: 10,
name: "Test_10",
points: [{…}, {…}, {…}],
label: "Label_10",
level: "1",
unit: "%"
},
{
Id: 20,
name: "Test_10",
points: [{…}, {…}, {…}, {…}],
label: "Label_10",
level: "1",
unit: "%"
},
{
Id: 30,
name: "Test_10",
points: [{…}, {…}, {…}],
label: "Label_10",
level: "2",
unit: "°C"
},
{
Id: 40,
name: "Test_10",
points: [{…}, {…}, {…}, {…}],
label: "Label_10",
level: "2",
unit: "°C"
}
]
转换/分组后,我想在下面显示此输出。我想在同一“级别”中结合所有点信息。这样我的输出在“ 1”级上就有七个点。但我只希望将其用于我的1级物品,而不是2级物品。是否有简单的方法可以实现? (也许吧,但对于ramda或rxjs之外的函数是必需的?)
const output =
[
{
Id: 10, // is not important for further code, can be first entry
name: "XX", // is not important for further code
points: [{…}, {…}, {…}, {…}, {…}, {…}, {…}], // all points now together
label: "Label_10",
level: "1",
unit: "%"
},
{
Id: 30,
name: "Test_10",
points: [{…}, {…}, {…}],
label: "Label_10",
level: "2",
unit: "°C"
},
{
Id: 40,
name: "Test_10",
points: [{…}, {…}, {…}, {…}],
label: "Label_10",
level: "2",
unit: "°C"
}
]
答案 0 :(得分:1)
我对下面的原始解决方案不满意。此版本不包含任何依赖关系,并且如果不是十分清晰,则是一个相当简单的ES6解决方案:
const combine = (a, b) =>
({...b, points: a .points .concat (b .points) })
const mergeLevel1Points = xs =>
[xs .filter (x => x .level == '1') .reduce (combine, {points: []}), ...xs .filter(x => x .level != '1')]
const input = [
{Id: 10, name: "Test_10", points: [1, 2, 3], label: "Label_10", level: "1", unit: "%"},
{Id: 20, name: "Test_10", points: [4, 5, 6, 7], label: "Label_10", level: "1", unit: "%"},
{Id: 30, name: "Test_10", points: [8, 9], label: "Label_10", level: "2", unit: "°C"},
{Id: 40, name: "Test_10", points: [10, 11, 12], label: "Label_10", level: "2", unit: "°C"}
]
console .log (
mergeLevel1Points (input)
)
它从最后一个level 1
元素而不是第一个元素保留数据。我确信可以很容易地更改它,但是问题很清楚,这并不重要,因此我保留了实现中的不足之处。
这是Ramda解决方案。我觉得它不是特别可读,但是要求本身就很奇怪,所以也许可以:
const combine = mergeWithKey (
(key, a, b) => key == 'points' ? concat(a, b) : a
)
const mergeLevel1Points = pipe (
partition (propEq ('level', '1') ),
apply (useWith (prepend, [reduce (combine, {})] ))
)
const input = [
{Id: 10, name: "Test_10", points: [1, 2, 3], label: "Label_10", level: "1", unit: "%"},
{Id: 20, name: "Test_10", points: [4, 5, 6, 7], label: "Label_10", level: "1", unit: "%"},
{Id: 30, name: "Test_10", points: [8, 9], label: "Label_10", level: "2", unit: "°C"},
{Id: 40, name: "Test_10", points: [10, 11, 12], label: "Label_10", level: "2", unit: "°C"}
]
console .log (
mergeLevel1Points (input)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>
const {mergeWithKey, concat, pipe, partition, propEq, apply, useWith, prepend, reduce} = R
</script>
combine
仅使用两项,大部分使用第一种,将其points
与第二项结合。也可以这样写:
const combine = (a, b) => ({...a, points: (a.points || []).concat(b.points)})
主要功能首先将输入分组为与level 1
匹配的输入和与partition
不匹配的输入。然后,它使用combine
(reduce(combine, {})
)将第一组折叠为单个值,并将结果附加到第二组。 apply
只是将我们两个参数的函数转换为一个接受包含两个参数的数组 的函数,以匹配partition
的输出。
由于使用了useWith
,这个版本对我来说有点令人反感;它是一个非常强大的功能,通常是简洁的功能,但通常会损害可读性。 (如果我将其用于公共功能,而不是匿名使用,那么我可能会在其上添加一个{identity
[useWith (prepend, [reduce (combine, {}), identity] )
],以便返回的函数正确地报告其Arity。但这只是次要点。)
仍然,这不是一个可怕的实现,它具有简洁的优点。
答案 1 :(得分:1)
net : The syntax of this command is:
At C:\Users\MyID\OneDrive - MyCompany\AD Group DropDown.ps1:34 char:64
+ ... path C:\Temp\RawIDs.txt | ForEach-Object {net user $_ /domain} >> C:\ ...
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (The syntax of this command is::String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
NET USER
[username [password | *] [options]] [/DOMAIN]
username {password | *} /ADD [options] [/DOMAIN]
username [/DELETE] [/DOMAIN]
username [/TIMES:{times | ALL}]
username [/ACTIVE: {YES | NO}]
const input = [
{Id: 10, name: "Test_10", points: [1, 2, 3], label: "Label_10", level: "1", unit: "%"},
{Id: 20, name: "Test_10", points: [4, 5, 6, 7], label: "Label_10", level: "1", unit: "%"},
{Id: 30, name: "Test_10", points: [8, 9], label: "Label_10", level: "2", unit: "°C"},
{Id: 40, name: "Test_10", points: [10, 11, 12], label: "Label_10", level: "2", unit: "°C"}
];
const mergeLevelOnePoint = R.pipe(
R.partition (R.propEq('level', '1')),
R.zipWith(
R.call,
[
R.pipe(
R.reduce
(R.mergeDeepWithKey((key, left, right) => (
key === 'points'
? R.concat(left, right)
: right
)))
({}),
R.of,
),
R.identity,
],
),
R.unnest,
);
console.log(mergeLevelOnePoint(input));
Ramda中一种更易理解的无点解决方案:
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
将输入拆分为R.partition
[ levelOneEntries, otherLevelEntries ]
,将其输出到R.zipWith(R.call, [fn1, fn2])
。 [fn1(levelOneEntries), fn2(otherLevelEntries)]
个深度合并的条目,串联了fn1
;而points
只是一个身份函数。fn2
将输出R.zipWith
,它是Array of Array的一种形式。因此,请使用[[mergedLevelOneEntry], otherLevelEntries]
展平为一个数组,即R.unnest
答案 2 :(得分:0)
您可以使用JavaScript的reduce()方法来做到这一点。
function groupByLevel(level) {
return input.reduce((arr, currentValue) => {
if (currentValue.level === level) {
const index = arr.findIndex(item => item.level === level);
if (index === -1) {
arr.push(currentValue);
} else {
arr[index].points = arr[index].points.concat(currentValue.points);
}
} else {
arr.push(currentValue);
}
return arr;
}, []);
}
演示:
const input = [{
Id: 10,
name: "Test_10",
points: [1, 2, 3],
label: "Label_10",
level: "1",
unit: "%"
},
{
Id: 20,
name: "Test_10",
points: [4, 5, 6, 7],
label: "Label_10",
level: "1",
unit: "%"
},
{
Id: 30,
name: "Test_10",
points: [1, 2, 3],
label: "Label_10",
level: "2",
unit: "°C"
},
{
Id: 40,
name: "Test_10",
points: [4, 5, 6, 7],
label: "Label_10",
level: "2",
unit: "°C"
}
]
function groupByLevel(level) {
return input.reduce((arr, currentValue) => {
if (currentValue.level === level) {
const index = arr.findIndex(item => item.level === level);
if (index === -1) {
arr.push(currentValue);
} else {
arr[index].points = arr[index].points.concat(currentValue.points);
}
} else {
arr.push(currentValue);
}
return arr;
}, []);
}
console.log(groupByLevel("1"));
答案 3 :(得分:0)
使用分组和过滤器 演示:
const input = [{
Id: 10,
name: "Test_10",
points: [1, 2, 3],
label: "Label_10",
level: "1",
unit: "%"
},
{
Id: 20,
name: "Test_10",
points: [4, 5, 6, 7],
label: "Label_10",
level: "1",
unit: "%"
},
{
Id: 30,
name: "Test_10",
points: [1, 2, 3],
label: "Label_10",
level: "2",
unit: "°C"
},
{
Id: 40,
name: "Test_10",
points: [4, 5, 6, 7],
label: "Label_10",
level: "2",
unit: "°C"
}
]
let levelsGroups;
function filterElement(el){
const topElement = levelsGroups[el.level]
if(!topElement){
levelsGroups[el.level] = el;
return true;
}
topElement.points.concat(el.points);
return false;
}
function groupInput() {
levelsGroups = {};
return input.filter(filterElement);
}
console.log(groupInput());