如何从JavaScript对象中具有关系的数字计算新值
How to calculate new values from numbers with relations in JavaScript object
我有以下数据:
[
{ "names" : [ "a3","printed","black" ], "value" : 15 },
{ "names" : [ "a3","copied","black" ], "value" : 87 },
{ "names" : [ "a3","printed","color" ], "value" : 37 },
{ "names" : [ "a3","printed","color","full" ], "value" : 37 },
{ "names" : [ "a3","copied","color","single" ], "value" : 0 },
{ "names" : [ "a3","copied","color","full" ], "value" : 44 },
{ "names" : [ "a3","scanned" ], "value" : 288 },
{ "names" : [ "total" ], "value" : 242142 },
{ "names" : [ "scanned" ], "value" : 67411 },
{ "names" : [ "copied","black" ], "value" : 79997 },
{ "names" : [ "copied","full","color" ], "value" : 809 },
{ "names" : [ "copied","single","color" ], "value" : 0 },
{ "names" : [ "printed","two","color" ], "value" : 0 },
{ "names" : [ "printed","black" ], "value" : 120665 },
{ "names" : [ "printed","full","color" ], "value" : 40657 }
]
我以以下方式组织了这些值之间的关系:
{
"colors" : { "black" : "", "color" : [ "full", "two", "single" ] },
"functions" : { "scanned" : "", "total" : [ "printed", "copied", "faxed" ] },
"papers" : { "a3" : "" }
}
使用这个脚本,我几乎得到了我想要的所有值:
function calculateValues(o) {
return Object.keys(o).reduce(function (r, k) {
var v;
if (k === 'value') {
return r;
}
v = calculateValues(o[k]);
if (o[k].value === null) {
o[k].value = v;
}
values[k] = (values[k] || 0) + o[k].value;
return r + o[k].value;
}, 0);
}
var data = [{ names: ["a3", "printed", "black"], value: 15 }, { names: ["a3", "copied", "black"], value: 87 }, { names: ["a3", "printed", "color"], value: 37 }, { names: ["a3", "printed", "color", "full"], value: 37 }, { names: ["a3", "copied", "color", "single"], value: 0 }, { names: ["a3", "copied", "color", "full"], value: 44 }, { names: ["a3", "scanned"], value: 288 }, { names: ["total"], value: 242142 }, { names: ["scanned"], value: 67411 }, { names: ["copied", "black"], value: 79997 }, { names: ["copied", "full", "color"], value: 809 }, { names: ["copied", "single", "color"], value: 0 }, { names: ["printed", "two", "color"], value: 0 }, { names: ["printed", "black"], value: 120665 }, { names: ["printed", "full", "color"], value: 40657 }],
relations = { colors: { "black": "", color: ["full", "two", "single"] }, functions: { scanned: "", total: ["printed", "copied", "faxed"] }, papers: { "a3": "" } },
priorities = ['functions', 'colors', 'papers'], // as long as keys of objects are not ordered
order = {},
result = {},
values = {},
i = 0;
priorities.forEach(function (p) {
Object.keys(relations[p]).forEach(function (k) {
order[k] = ++i;
Array.isArray(relations[p][k]) && relations[p][k].forEach(function (a) {
order[a] = ++i;
});
});
});
data.forEach(function (a) {
var names = a.names.slice();
names.sort(function (a, b) {
return (order[a] || 0) - (order[b] || 0);
});
if (relations.functions.total.indexOf(names[0]) !== -1) {
names.unshift('total');
}
names.reduce(function (o, k) {
return o[k] = o[k] || { value: null };
}, result).value = a.value;
});
calculateValues(result.total);
// calculateCount(result.scanned);
console.log(values);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
但我错过了一些东西。例如:
a3打印黑色是15
a3打印颜色为37
什么是a3打印?(52(
另一个是:
a3复制的全彩色是:44
a3复制的彩色单曲是:0
什么是a3复制的颜色?(44(
另一个是:
a3打印颜色为:37
a3复制的颜色为:44(基于我们在上面找到的值示例(
什么是a3颜色?81
你可能应该明白我的意思是这里缺少什么。
您可以在result
对象中搜索给定的指示符并迭代所有属性。然后只计算匹配的值。
function getValue(names) {
function iter(o, p) {
Object.keys(o).forEach(function (k) {
var q = p.slice();
k === q[0] && q.shift();
if (q.length) {
o[k] !== null && typeof o[k] === 'object' && iter(o[k], q);
return;
}
v += o[k].value || 0;
});
}
var v = 0;
names.sort(sortByOrder);
iter(result, names);
return v;
}
function calculateValues(o) {
return Object.keys(o).reduce(function (r, k) {
var v;
if (k === 'value') {
return r;
}
v = calculateValues(o[k]);
if (o[k].value === null) {
o[k].value = v;
}
values[k] = (values[k] || 0) + o[k].value;
return r + o[k].value;
}, 0);
}
function sortByOrder(a, b) {
return (order[a] || 0) - (order[b] || 0);
}
function getSums(a) {
console.log(a.join(' '), getValue(a));
}
var data = [{ names: ["a3", "printed", "black"], value: 15 }, { names: ["a3", "copied", "black"], value: 87 }, { names: ["a3", "printed", "color", "full"], value: 37 }, { names: ["a3", "copied", "color", "single"], value: 0 }, { names: ["a3", "copied", "color", "full"], value: 44 }, { names: ["a3", "scanned"], value: 288 }, { names: ["total"], value: 242142 }, { names: ["scanned"], value: 67411 }, { names: ["copied", "black"], value: 79997 }, { names: ["copied", "full", "color"], value: 809 }, { names: ["copied", "single", "color"], value: 0 }, { names: ["printed", "two", "color"], value: 0 }, { names: ["printed", "black"], value: 120665 }, { names: ["printed", "full", "color"], value: 40657 }],
relations = { colors: { "black": "", color: ["full", "two", "single"] }, functions: { scanned: "", total: ["printed", "copied", "faxed"] }, papers: { "a3": "" } },
priorities = ['functions', 'colors', 'papers'], // as long as keys of objects are not ordered
order = {},
result = {},
values = {},
i = 0;
priorities.forEach(function (p) {
Object.keys(relations[p]).forEach(function (k) {
order[k] = ++i;
Array.isArray(relations[p][k]) && relations[p][k].forEach(function (a) {
order[a] = ++i;
});
});
});
data.forEach(function (a) {
var names = a.names.slice();
names.sort(sortByOrder);
if (relations.functions.total.indexOf(names[0]) !== -1) {
names.unshift('total');
}
names.reduce(function (o, k) {
return o[k] = o[k] || { value: null };
}, result).value = a.value;
});
calculateValues(result.total);
// calculateCount(result.scanned);
getSums(['a3', 'color']);
getSums(['a3', 'black']);
getSums(['a3', 'printed', 'two', 'color']);
getSums(['a3', 'printed', 'full', 'color']);
// the wanted use cases
getSums(['a3', 'printed', 'black']); // 15
getSums(['a3', 'printed', 'color']); // 37
getSums(['a3', 'printed']); // 52
getSums(['a3', 'copied', 'color', 'full']); // 44
getSums(['a3', 'copied', 'color', 'single']); // 0
getSums(['a3', 'copied', 'color']); // 44
getSums(['a3', 'printed', 'color']); // 37
getSums(['a3', 'copied', 'color']); // 44
getSums(['a3', 'color']); // 81
console.log(values);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我还没有考虑过你的另一个问题,但对我来说,似乎只需要求和,你就可以使用一个简单得多的函数。
- 使用
filter
在其names
数组中选择具有所有所需值的条目 - 使用
reduce
添加其value
属性
function getEntriesWithValues(entries, values) {
return entries
.filter(e => values.every(v => e.names.includes(v)));
};
function sumValue(v1, v2) { return v1 + v2.value; }
var data = [
{ "names" : [ "a3","printed","black" ], "value" : 15 },
{ "names" : [ "a3","copied","black" ], "value" : 87 },
{ "names" : [ "a3","printed","color","full" ], "value" : 37 },
{ "names" : [ "a3","copied","color","single" ], "value" : 0 },
{ "names" : [ "a3","copied","color","full" ], "value" : 44 },
{ "names" : [ "a3","scanned" ], "value" : 288 },
{ "names" : [ "total" ], "value" : 242142 },
{ "names" : [ "scanned" ], "value" : 67411 },
{ "names" : [ "copied","black" ], "value" : 79997 },
{ "names" : [ "copied","full","color" ], "value" : 809 },
{ "names" : [ "copied","single","color" ], "value" : 0 },
{ "names" : [ "printed","two","color" ], "value" : 0 },
{ "names" : [ "printed","black" ], "value" : 120665 },
{ "names" : [ "printed","full","color" ], "value" : 40657 }
];
function getSumFromData(values) {
return getEntriesWithValues(data, values).reduce(sumValue, 0);
};
var entriesWithA3Black = getEntriesWithValues(data, ["a3", "black"]);
var sumForA3Black = entriesWithA3Black.reduce(sumValue, 0);
console.log("Sum for A3 + black: " + sumForA3Black);
console.log("Sum for A3 + color: " + getSumFromData(["a3", "color"]));
相关文章:
- 一个jquery验证器方法,它不接受纯数字或纯特殊字符,但接受上面是否有字母
- 有没有办法在里面看到一个数字'的64位浮点IEEE754表示
- 为什么 JavaScript 如果一个数字有一个前导零,就将其视为八进制
- JavaScriptV5中的绑定和JQuery之间有任何关系吗
- 这个javascript代码有什么错误,它有将数字转换为单词的功能
- 如何创建一个计数器循环,该循环在单击提交按钮时启动,并输出多行单词,每个单词前面都有一个数字
- fancybox/jQuery:为什么可以'我点击了一个与粉丝盒有关系的按钮后就放弃了
- 在其他脚本之前或之后加载html5shivJS有关系吗?(页面加载时间)
- 如果我追加的内容似乎只依赖于.append()调用,那么在数据连接期间我将哪个项传递给d3.selectAll()有关系
- Javascript-确保输入至少有一个数字
- Regex Javascript(必须有一个数字和字符)
- 逐行读取文本文件.使用什么浏览器有关系吗?
- 我在输入元素上列出下列内容的顺序有关系吗?
- node.js中有大数字的位运算符
- 我有一个数字,我想在jquery数组中得到小于和大于的最接近的数字
- 什么“?在 JavaScript 之后有一个数字是针对的
- 我应该设置什么大小的 MaxJsonLength?有关系吗
- 六个字符的正则表达式,至少有一个数字
- 查找与节点列表有关系的节点
- 有法国数字的特殊排序