我发现这个:count occurrences of search strings in a list (python) 与我需要的解决方案相似,但在 javascript 中。
我有对象数组:
data_items = [
{
"no": "1",
"category": "design",
"class": "low",
"status": "open",
},
{
"no": "2",
"category": "permit",
"class": "low",
"status": "close",
},
{
"no": "3",
"category": "permit",
"class": "high",
"status": "open",
},
{
"no": "4",
"category": "quality",
"class": "high",
"status": "close",
}
]
和
categoryList = [
"design",
"permit",
"quality",
"safety",
"commercial"
]
我期望的是计算每个类别包括空结果的出现次数
countCategories = [
{ "design": 1 },
{ "permit": 2 },
{ "quality": 1 },
{ "safety": 0 },
{ "commercial": 0 }
]
以及如何获得结果的多维版本?比如
countCategories = [
{
open: [
{ "design": 1 },
{ "permit": 1 },
{ "quality": 0 },
{ "safety": 0 },
{ "commercial": 0 }
]
}, {
close: [
{ "design": 0 },
{ "permit": 1 },
{ "quality": 1 },
{ "safety": 0 },
{ "commercial": 0 }
]
}
]
我一直在尝试通过减少和过滤来获得结果,但没有成功
感谢您的帮助。
答案 0 :(得分:0)
您可以像这样计算所有类别,然后将其转换为您想要的任何格式:
const data_items = [{
"no": "1",
"category": "design",
"class": "low",
"status": "open",
},
{
"no": "2",
"category": "permit",
"class": "low",
"status": "close",
},
{
"no": "3",
"category": "permit",
"class": "high",
"status": "open",
},
{
"no": "4",
"category": "quality",
"class": "high",
"status": "close",
}
]
const counting = new Map();
for (const item of data_items) {
let count = counting.get(item.category) || 0;
counting.set(item.category, count + 1);
}
// Convert it to the format you wanted (even though it's a weird one)
const countCategories = [];
for (const [key, value] of counting) {
countCategories.push({
[key]: value
});
}
console.log(countCategories);
// [
// {design: 1},
// {permit: 2},
// {quality: 1},
// ]
编辑:在我撰写此答案时,您似乎添加了多维版本的要求。您可以重复使用上述代码并运行两次,但一次过滤 item.status === 'open'
,另一次过滤 'close'
。这将为您提供两个结果数组,您可以将它们组合成一个多维版本。
答案 1 :(得分:0)
reduce 的基本思想。
var obj = {
data_items: [{
"no": "1",
"category": "design",
"class": "low",
"status": "open",
},
{
"no": "2",
"category": "permit",
"class": "low",
"status": "close",
},
{
"no": "3",
"category": "permit",
"class": "high",
"status": "open",
},
{
"no": "4",
"category": "quality",
"class": "high",
"status": "close",
}
]
}
const result = obj.data_items.reduce(function(acc, item) {
acc[item.status][item.category] = (acc[item.status][item.category] || 0) + 1;
return acc;
}, {
open: {},
close: {}
});
console.log(result);
如果你想用零预填充你的对象
var obj = {
categoryList: [
"design",
"permit",
"quality",
"safety",
"commercial"
],
data_items: [{
"no": "1",
"category": "design",
"class": "low",
"status": "open",
},
{
"no": "2",
"category": "permit",
"class": "low",
"status": "close",
},
{
"no": "3",
"category": "permit",
"class": "high",
"status": "open",
},
{
"no": "4",
"category": "quality",
"class": "high",
"status": "close",
}
]
}
const defaultObj = obj.categoryList.reduce(function (acc, key) {
acc[key] = 0;
return acc;
}, {});
const result = obj.data_items.reduce(function(acc, item) {
acc[item.status][item.category] += 1;
return acc;
}, {
open: { ...defaultObj
},
close: { ...defaultObj
}
});
console.log(result);
答案 2 :(得分:0)
使用 reduce 是可行的方法,因为您可以使用打开/关闭数组开始您的最终对象。我添加了一个副本,以便显示它如何根据条件递增。
let data_items = [{
"no": "1",
"category": "design",
"class": "low",
"status": "open",
},
{
"no": "2",
"category": "permit",
"class": "low",
"status": "close",
},
{
"no": "3",
"category": "permit",
"class": "high",
"status": "open",
},
{
"no": "4",
"category": "quality",
"class": "high",
"status": "close",
},
{
"no": "5",
"category": "quality",
"class": "high",
"status": "close",
}
]
let result = data_items.reduce((b, a) => {
let l = b[a.status].findIndex(e => Object.keys(e)[0] === a.category)
if (l > -1) b[a.status][l][a.category]++;
else {
b.open.push({
[a.category]: a.status === 'open' ? 1 : 0
});
b.close.push({
[a.category]: a.status === 'close' ? 1 : 0
});
}
return b
}, {
open: [],
close: []
})
console.log(result)
答案 3 :(得分:0)
您可以使用通常称为 groupBy
的通用分组函数来避免硬编码状态值(打开和关闭)。首先使用 status
键应用它。
然后,在每个状态中,类别计数是一个直接的 reduce()。
最后一个可能是可选的步骤是将对象结果转换为数组(如 OP 所述)...
const data_items = [
{
"no": "1",
"category": "design",
"class": "low",
"status": "open",
},
{
"no": "2",
"category": "permit",
"class": "low",
"status": "close",
},
{
"no": "3",
"category": "permit",
"class": "high",
"status": "open",
},
{
"no": "4",
"category": "quality",
"class": "high",
"status": "close",
}
]
// answer an object where each key is the value of key in the array
// and each value is an array of elements with the given key's values
function groupBy(array, key) {
return array.reduce((acc, el) => {
let value = el[key];
if (!acc[value]) acc[value] = [];
acc[value].push(el);
return acc;
}, {});
}
function reduceToCategories(array) {
return array.reduce((acc, obj) => {
const cat = obj['category'];
if (!acc[cat]) acc[cat] = 0;
acc[cat]++;
return acc;
}, {})
}
let groups = groupBy(data_items, 'status');
let result = {}
for (status in groups) {
result[status] = reduceToCategories(groups[status])
}
// result in an object, rather than an array as the OP requests.
// If an array is necessary, the straight-forward transformation is...
const countCategories = Object.entries(result).map(([key, value]) => ({ [key] : value }))
console.log(countCategories)
答案 4 :(得分:0)
您可以构建频率图,然后将条目映射到键值对对象列表。
const dataItems = [
{ "no": "1", "category": "design" , "class": "low" , "status": "open" },
{ "no": "2", "category": "permit" , "class": "low" , "status": "close" },
{ "no": "3", "category": "permit" , "class": "high", "status": "open" },
{ "no": "4", "category": "quality", "class": "high", "status": "close" }
];
const unique = (arr, fn) => [...new Set(arr.map(item => fn(item)).sort())];
const frequency = (arr, keyFn) =>
arr.reduce((acc, item) =>
(key => ({ ...acc, [key]: (acc[key] || 0) + 1 }))
(keyFn ? keyFn(item) : item), {});
const mapToPairs = (map) => Object.entries(map).map(([ k, v ]) => ({ [k]: v }));
const categoryList = unique(dataItems, ({ category }) => category);
console.log(JSON.stringify(categoryList));
const catFreq = mapToPairs(frequency(dataItems, ({ category }) => category));
console.log(JSON.stringify(catFreq));
const freq = dataItems
.reduce((acc, { status, category }) =>
({ ...acc, [status]: [...(acc[status] || []), { category }] }), {});
for (let key in freq) {
freq[key] = mapToPairs(frequency(freq[key], ({ category }) => category));
}
console.log((JSON.stringify(freq)));
.as-console-wrapper { top: 0; max-height: 100% !important; }
答案 5 :(得分:0)
感谢您的回答, 自从我发布这篇文章以来,我一直在尝试,我带来了:
function map_it(data_items, dim_key) {
var bucket = {};
categoryList.forEach(function (cat) {
bucket[cat] = 0;
})
data_items.forEach(function (item) {
if (Object.keys(bucket).indexOf(item.category) >= 0) bucket[item.category]++;
else bucket[item.category] = 1;
})
return bucket;
}
console.log(map_it(data_items));