使用 ramda.js 将嵌套对象数组中的键值与标识符键匹配
Match values of a key in a nested array of objects to an identifier key using ramda.js
我正在尝试将这个嵌套对象数组和数组以及 return 该特定对象的标识符的总分得分放入一个新对象中。这是我正在使用的 JSON:
{
"AllData" : [ {
"company" : google,
"featureData" : [{
"ScoreTotal" : 10,
"featureName": 'test'
},{
"ScoreTotal" : 10,
"featureName": 'test2'
},
{
"ScoreTotal" : 4,
"featureName": 'test3'
}]
}, {
"company" : amazon,
"featureData" : [{
"ScoreTotal" : 4,
"featureName": 'test'
},{
"ScoreTotal" : 6,
"featureName": 'test2'
},
{
"ScoreTotal" : 3,
"featureName": 'test3'
}]
},{
"company" : facebook,
"featureData" : [{
"ScoreTotal" : 4,
"featureName": 'test' },
{
"ScoreTotal" : 6,
"featureName": 'test2' },
{
"ScoreTotal" : 2,
"featureName": 'test3'
}]
},
}]
}
我正在尝试创建一个对象数组,其中包含每个唯一 featureName 的得分总和以及相应的 featureName,如下所示:
[{featureName: 'test1', summedScore: '18'}, {featureName: 'test2', summedScore: '22'},{featureName: 'test3', summedScore: ' 9'}]
可以找到接近我要找的解决方案,但是解决方案中没有显示标识符与总和的匹配。
提前致谢!
我正在创建一个对象,我在其中使用特征的名称作为键,因此很容易创建他们的总分。然后我把这个对象变成符合你期望的数组。
const json = {
"AllData": [{
"company": 'google',
"featureData": [{
"ScoreTotal": 10,
"featureName": 'test'
}, {
"ScoreTotal": 10,
"featureName": 'test2'
},
{
"ScoreTotal": 4,
"featureName": 'test3'
}
]
}, {
"company": 'amazon',
"featureData": [{
"ScoreTotal": 4,
"featureName": 'test'
}, {
"ScoreTotal": 6,
"featureName": 'test2'
},
{
"ScoreTotal": 3,
"featureName": 'test3'
}
]
}, {
"company": 'facebook',
"featureData": [{
"ScoreTotal": 4,
"featureName": 'test'
},
{
"ScoreTotal": 6,
"featureName": 'test2'
},
{
"ScoreTotal": 2,
"featureName": 'test3'
}
]
}]
};
const obj = json.AllData.reduce((tmp, x) => {
x.featureData.forEach((y) => {
tmp[y.featureName] = (tmp[y.featureName] || 0) + y.ScoreTotal;
});
return tmp;
}, {});
const arr = Object.keys(obj).map(x => ({
summedScore: obj[x],
featureName: x,
}));
console.log(arr);
这是 Ramda 的解决方案
const data = {
"AllData": [{
"company": "google",
"featureData": [{
"ScoreTotal": 10,
"featureName": 'test'
}, {
"ScoreTotal": 10,
"featureName": 'test2'
},
{
"ScoreTotal": 4,
"featureName": 'test3'
}]
}, {
"company": "amazon",
"featureData": [{
"ScoreTotal": 4,
"featureName": 'test'
}, {
"ScoreTotal": 6,
"featureName": 'test2'
},
{
"ScoreTotal": 3,
"featureName": 'test3'
}]
}, {
"company": "facebook",
"featureData": [{
"ScoreTotal": 4,
"featureName": 'test'
},
{
"ScoreTotal": 6,
"featureName": 'test2'
},
{
"ScoreTotal": 2,
"featureName": 'test3'
}]
}
]
};
const getScores =
R.pipe(
// Group all featureData objects into a single array
R.prop('AllData'),
R.map(R.prop('featureData')),
R.unnest,
// Group all featureData objects with the same featureName into separate arrays
R.groupBy(R.prop('featureName')),
// Merge all objects in each array by summing their `ScoreTotal` properties
R.map(R.reduce(R.mergeWithKey((key, left, right) => key === 'ScoreTotal' ? left + right : right), {})),
R.values,
// Reshape each object
R.map(R.applySpec({
featureName: R.prop('featureName'),
summedScore: R.prop('ScoreTotal')
})));
console.log(
getScores(data)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
我喜欢像这样一步一步地进行转换,从原始数据开始,一直到最终格式。我可以在 Ramda's REPL with a pipe
调用中执行此操作,逐个添加各个调用并检查结果是否朝着我想要的方向发展。
这样做,这就是我想出的答案。
const {pipe, prop, pluck, unnest, groupBy, map, sum, toPairs, zipObj} = R
const sumByFeatureName = pipe(
prop('AllData'),
pluck('featureData'),
unnest,
groupBy(prop('featureName')),
map(pluck('ScoreTotal')),
map(sum),
toPairs,
map(zipObj(['featureName', 'summedScore'])),
)
const json = {"AllData": [{"company": "google", "featureData": [{"ScoreTotal": 10, "featureName": "test"}, {"ScoreTotal": 10, "featureName": "test2"}, {"ScoreTotal": 4, "featureName": "test3"}]}, {"company": "amazon", "featureData": [{"ScoreTotal": 4, "featureName": "test"}, {"ScoreTotal": 6, "featureName": "test2"}, {"ScoreTotal": 3, "featureName": "test3"}]}, {"company": "facebook", "featureData": [{"ScoreTotal": 4, "featureName": "test"}, {"ScoreTotal": 6, "featureName": "test2"}, {"ScoreTotal": 2, "featureName": "test3"}]}]}
console.log(sumByFeatureName(json))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
这演示了所有中间结果的结构:
const sumByFeatureName = pipe(
prop('AllData'), //=> [{company: "google", featureData: [{ScoreTotal: 10, featureName: "test"}, ...], {company: 'amazon', ...}, ...]
pluck('featureData'), //=> [[{ScoreTotal: 10, featureName: 'test"}, {ScoreTotal: 10, featureName: 'test2'}, ...] [...], ...]
unnest, //=> [{ScoreTotal: 10, featureName: 'test'}, {ScoreTotal: 10, featureName: 'test2'}, ...]
groupBy(prop('featureName')), //=> {test: [{ScoreTotal: 10, featureName: 'test'}, ...], test2: [{...}, ...]}
map(pluck('ScoreTotal')), //=> {test: [10, 4, 4], test2: [10, 6, 6], test3: [4, 3, 2]}
map(sum), //=> {test: 18, test2: 22, test3: 9}
toPairs, //=> [['test', 18], ['test2', 22], ['test3', 9]]
map(zipObj(['featureName', 'summedScore'])), //=> [{featureName: 'test, summedScore: 19}, ...]
)
请注意,如果我们删除最后两行(toPairs
和 map(zipObj(...))
),我们将得到以下格式:
{test: 18, test2: 22, test3: 9}
这通常是比您请求的输出更有用的结构。
另请注意,此类工作有助于确定我们自己的实用程序库中可能需要的有用功能,甚至建议将其添加到像 Ramda 这样的库中。如果我已经完成 toPairs
/map(zipObj(...))
洗牌足够多次,我可能会考虑为它编写自己的小函数,例如:
const objArray = (keyName, valName) => vals =>
map(zipObj([keyName, valName]), toPairs(vals))
然后用 objArray('featureName', 'summedScore')
.
替换这两行
我正在尝试将这个嵌套对象数组和数组以及 return 该特定对象的标识符的总分得分放入一个新对象中。这是我正在使用的 JSON:
{
"AllData" : [ {
"company" : google,
"featureData" : [{
"ScoreTotal" : 10,
"featureName": 'test'
},{
"ScoreTotal" : 10,
"featureName": 'test2'
},
{
"ScoreTotal" : 4,
"featureName": 'test3'
}]
}, {
"company" : amazon,
"featureData" : [{
"ScoreTotal" : 4,
"featureName": 'test'
},{
"ScoreTotal" : 6,
"featureName": 'test2'
},
{
"ScoreTotal" : 3,
"featureName": 'test3'
}]
},{
"company" : facebook,
"featureData" : [{
"ScoreTotal" : 4,
"featureName": 'test' },
{
"ScoreTotal" : 6,
"featureName": 'test2' },
{
"ScoreTotal" : 2,
"featureName": 'test3'
}]
},
}]
}
我正在尝试创建一个对象数组,其中包含每个唯一 featureName 的得分总和以及相应的 featureName,如下所示:
[{featureName: 'test1', summedScore: '18'}, {featureName: 'test2', summedScore: '22'},{featureName: 'test3', summedScore: ' 9'}]
可以找到接近我要找的解决方案
提前致谢!
我正在创建一个对象,我在其中使用特征的名称作为键,因此很容易创建他们的总分。然后我把这个对象变成符合你期望的数组。
const json = {
"AllData": [{
"company": 'google',
"featureData": [{
"ScoreTotal": 10,
"featureName": 'test'
}, {
"ScoreTotal": 10,
"featureName": 'test2'
},
{
"ScoreTotal": 4,
"featureName": 'test3'
}
]
}, {
"company": 'amazon',
"featureData": [{
"ScoreTotal": 4,
"featureName": 'test'
}, {
"ScoreTotal": 6,
"featureName": 'test2'
},
{
"ScoreTotal": 3,
"featureName": 'test3'
}
]
}, {
"company": 'facebook',
"featureData": [{
"ScoreTotal": 4,
"featureName": 'test'
},
{
"ScoreTotal": 6,
"featureName": 'test2'
},
{
"ScoreTotal": 2,
"featureName": 'test3'
}
]
}]
};
const obj = json.AllData.reduce((tmp, x) => {
x.featureData.forEach((y) => {
tmp[y.featureName] = (tmp[y.featureName] || 0) + y.ScoreTotal;
});
return tmp;
}, {});
const arr = Object.keys(obj).map(x => ({
summedScore: obj[x],
featureName: x,
}));
console.log(arr);
这是 Ramda 的解决方案
const data = {
"AllData": [{
"company": "google",
"featureData": [{
"ScoreTotal": 10,
"featureName": 'test'
}, {
"ScoreTotal": 10,
"featureName": 'test2'
},
{
"ScoreTotal": 4,
"featureName": 'test3'
}]
}, {
"company": "amazon",
"featureData": [{
"ScoreTotal": 4,
"featureName": 'test'
}, {
"ScoreTotal": 6,
"featureName": 'test2'
},
{
"ScoreTotal": 3,
"featureName": 'test3'
}]
}, {
"company": "facebook",
"featureData": [{
"ScoreTotal": 4,
"featureName": 'test'
},
{
"ScoreTotal": 6,
"featureName": 'test2'
},
{
"ScoreTotal": 2,
"featureName": 'test3'
}]
}
]
};
const getScores =
R.pipe(
// Group all featureData objects into a single array
R.prop('AllData'),
R.map(R.prop('featureData')),
R.unnest,
// Group all featureData objects with the same featureName into separate arrays
R.groupBy(R.prop('featureName')),
// Merge all objects in each array by summing their `ScoreTotal` properties
R.map(R.reduce(R.mergeWithKey((key, left, right) => key === 'ScoreTotal' ? left + right : right), {})),
R.values,
// Reshape each object
R.map(R.applySpec({
featureName: R.prop('featureName'),
summedScore: R.prop('ScoreTotal')
})));
console.log(
getScores(data)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
我喜欢像这样一步一步地进行转换,从原始数据开始,一直到最终格式。我可以在 Ramda's REPL with a pipe
调用中执行此操作,逐个添加各个调用并检查结果是否朝着我想要的方向发展。
这样做,这就是我想出的答案。
const {pipe, prop, pluck, unnest, groupBy, map, sum, toPairs, zipObj} = R
const sumByFeatureName = pipe(
prop('AllData'),
pluck('featureData'),
unnest,
groupBy(prop('featureName')),
map(pluck('ScoreTotal')),
map(sum),
toPairs,
map(zipObj(['featureName', 'summedScore'])),
)
const json = {"AllData": [{"company": "google", "featureData": [{"ScoreTotal": 10, "featureName": "test"}, {"ScoreTotal": 10, "featureName": "test2"}, {"ScoreTotal": 4, "featureName": "test3"}]}, {"company": "amazon", "featureData": [{"ScoreTotal": 4, "featureName": "test"}, {"ScoreTotal": 6, "featureName": "test2"}, {"ScoreTotal": 3, "featureName": "test3"}]}, {"company": "facebook", "featureData": [{"ScoreTotal": 4, "featureName": "test"}, {"ScoreTotal": 6, "featureName": "test2"}, {"ScoreTotal": 2, "featureName": "test3"}]}]}
console.log(sumByFeatureName(json))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
这演示了所有中间结果的结构:
const sumByFeatureName = pipe(
prop('AllData'), //=> [{company: "google", featureData: [{ScoreTotal: 10, featureName: "test"}, ...], {company: 'amazon', ...}, ...]
pluck('featureData'), //=> [[{ScoreTotal: 10, featureName: 'test"}, {ScoreTotal: 10, featureName: 'test2'}, ...] [...], ...]
unnest, //=> [{ScoreTotal: 10, featureName: 'test'}, {ScoreTotal: 10, featureName: 'test2'}, ...]
groupBy(prop('featureName')), //=> {test: [{ScoreTotal: 10, featureName: 'test'}, ...], test2: [{...}, ...]}
map(pluck('ScoreTotal')), //=> {test: [10, 4, 4], test2: [10, 6, 6], test3: [4, 3, 2]}
map(sum), //=> {test: 18, test2: 22, test3: 9}
toPairs, //=> [['test', 18], ['test2', 22], ['test3', 9]]
map(zipObj(['featureName', 'summedScore'])), //=> [{featureName: 'test, summedScore: 19}, ...]
)
请注意,如果我们删除最后两行(toPairs
和 map(zipObj(...))
),我们将得到以下格式:
{test: 18, test2: 22, test3: 9}
这通常是比您请求的输出更有用的结构。
另请注意,此类工作有助于确定我们自己的实用程序库中可能需要的有用功能,甚至建议将其添加到像 Ramda 这样的库中。如果我已经完成 toPairs
/map(zipObj(...))
洗牌足够多次,我可能会考虑为它编写自己的小函数,例如:
const objArray = (keyName, valName) => vals =>
map(zipObj([keyName, valName]), toPairs(vals))
然后用 objArray('featureName', 'summedScore')
.