如果属性值为true,则按多个属性分组
Lodash group by multiple properties if property value is true
我有一个车辆数组,只有当'selected'属性为真时,才需要按make和model进行分组。结果对象应该包含make model和count的属性。使用lodash,我如何将车辆对象组织为所需的结果对象。我能够获得由makeCode分组的车辆对象,但我不确定如何通过多个属性分组。
集团通过使代码作品
var vehicles = _.groupBy(response.vehicleTypes, function(item)
{
return item.makeCode; // how to group by model code as well
});
初始车辆
{
id: 1,
selected: true,
makeCode: "Make-A",
modelCode: "Model-a",
trimCode: "trim-a",
yearCode: "2012"
},
{
id: 2,
selected: false,
makeCode: "Make-A",
modelCode: "Model-a",
trimCode: "trim-a",
yearCode: "2013"
},
{
id: 3,
selected: true,
makeCode: "Make-B",
modelCode: "Model-c",
trimCode: "trim-a",
yearCode: "2014"
},
{
id: 25,
selected: true,
makeCode: "Make-C",
modelCode: "Model-b",
trimCode: "trim-b",
yearCode: "2012"
},
{
id: 26,
selected: true,
makeCode: "Make-C",
modelCode: "Model-b",
trimCode: "trim-a",
yearCode: "2013"
}
结果对象
{
Make-A: {
Model-a: {
count: 1
}
}
},
{
Make-B: {
Model-c: {
count: 1
}
}
},
{
Make-C: {
Model-b: {
count: 2
}
}
}
我不确定这是否会解决您的问题,但在group_by中,您可以添加自定义逻辑,允许您创建复合键。
请记住,分隔符值应该根据您使用的数据源来定义,如果"——"字符出现在模型或类型中,您不应该使用它们,因为它将不允许您逆转分组过程。
const SEPERATOR = "--";
_.chain(data).filter((item) => item.selected).groupBy((item)=>`${item.model}${SEPERATOR}${item.type}`).value();
既然已经使用了lodash,那么可以利用_。过滤功能。这将只返回selected
为真的项。
var selectedVehicles = _.filter(response.vehicleTypes, 'selected');
现在您有了selectedVehicles
数组,您可以使用原始代码按makeCode
进行分组。
selectedVehicles = _.groupBy(selectedVehicles, function(item) {
return item.makeCode;
});
返回一个对象,因此我们需要遍历这些键,并执行第二个groupBy
_.forEach(selectedVehicles, function(value, key) {
selectedVehicles[key] = _.groupBy(selectedVehicles[key], function(item) {
return item.modelCode;
});
});
从这里你将得到一个形式的对象。我将让您从每个数组中获取计数。
{ 'Make-A': { 'Model-a': [ ... ] },
'Make-B': { 'Model-c': [ ... ] },
'Make-C': { 'Model-b': [ ..., ... ] } }
如果你关注结果,下面的代码可以工作:
在我的例子中,Brand
和Item Code
是属性
const products = _.groupBy(this.productsTable.data, (item) => {
return [item['Brand'], item['Item Code']];
});
您可以使用Array.prototype.reduce()
,并在一个循环中完成O(n):
var arr = [{"id":1,"selected":true,"makeCode":"Make-A","modelCode":"Model-a","trimCode":"trim-a","yearCode":"2012"},{"id":2,"selected":false,"makeCode":"Make-A","modelCode":"Model-a","trimCode":"trim-a","yearCode":"2013"},{"id":3,"selected":true,"makeCode":"Make-B","modelCode":"Model-c","trimCode":"trim-a","yearCode":"2014"},{"id":25,"selected":true,"makeCode":"Make-C","modelCode":"Model-b","trimCode":"trim-b","yearCode":"2012"},{"id":26,"selected":true,"makeCode":"Make-C","modelCode":"Model-b","trimCode":"trim-a","yearCode":"2013"},{"id":29,"selected":false,"makeCode":"Make-A","modelCode":"Model-g","trimCode":"trim-a","yearCode":"2013"},{"id":2,"selected":true,"makeCode":"Make-A","modelCode":"Model-h","trimCode":"trim-a","yearCode":"2013"}];
var result = arr.reduce(function(map, obj) {
if(!obj.selected) {
return map;
}
var makeCode = map[obj.makeCode] = map[obj.makeCode] || {};
var modelCode = makeCode[obj.modelCode] = makeCode[obj.modelCode] || { count: 0 };
modelCode.count++;
return map;
}, Object.create(null));
console.log(result);
使用解构的更可读、更现代的版本:
const arr = [{"id":1,"selected":true,"makeCode":"Make-A","modelCode":"Model-a","trimCode":"trim-a","yearCode":"2012"},{"id":2,"selected":false,"makeCode":"Make-A","modelCode":"Model-a","trimCode":"trim-a","yearCode":"2013"},{"id":3,"selected":true,"makeCode":"Make-B","modelCode":"Model-c","trimCode":"trim-a","yearCode":"2014"},{"id":25,"selected":true,"makeCode":"Make-C","modelCode":"Model-b","trimCode":"trim-b","yearCode":"2012"},{"id":26,"selected":true,"makeCode":"Make-C","modelCode":"Model-b","trimCode":"trim-a","yearCode":"2013"},{"id":29,"selected":false,"makeCode":"Make-A","modelCode":"Model-g","trimCode":"trim-a","yearCode":"2013"},{"id":2,"selected":true,"makeCode":"Make-A","modelCode":"Model-h","trimCode":"trim-a","yearCode":"2013"}];
const result = arr.reduce((acc, { selected, makeCode, modelCode }) => {
if(!selected) return acc;
if(!acc[makeCode]) acc[makeCode] = {};
const make = acc[makeCode];
if(!make[modelCode]) make[modelCode] = { count: 0 };
make[modelCode].count++;
return acc;
}, Object.create(null));
console.log(result);
const result = _.chain(vehicles)
.filter('selected')
.groupBy('makeCode')
.mapValues(values => _.chain(values)
.groupBy('modelCode')
.mapValues(_.size)
.value()
)
.value()
const multiGroupBy = (array, group, ...restGroups) => {
if(!group) {
return array;
}
const currGrouping = _.groupBy(array, group);
if(!restGroups.length) {
return currGrouping;
}
return _.transform(currGrouping, (result, value, key) => {
result[key] = multiGroupBy(value, ...restGroups);
}, {});
};
console.log(multiGroupBy([{x:1,y:1,z:1},{x:1,y:2,z:1},{x:2,y:1,z:1},{x:2,y:2,z:1},{x:1,y:1,z:2},{x:1,y:2,z:2},{x:2,y:1,z:2},{x:2,y:2,z:2}],'x','y'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
或者如果你喜欢旧语法
function multiGroupBy(array, group) {
if(!group) {
return array;
}
var currGrouping = _.groupBy(array, group);
var restGroups = Array.prototype.slice.call(arguments);
restGroups.splice(0,2);
if(!restGroups.length) {
return currGrouping;
}
return _.transform(currGrouping, function(result, value, key) {
result[key] = multiGroupBy.apply(null, [value].concat(restGroups));
}, {});
}
console.log(multiGroupBy([{x:1,y:1,z:1},{x:1,y:2,z:1},{x:2,y:1,z:1},{x:2,y:2,z:1},{x:1,y:1,z:2},{x:1,y:2,z:2},{x:2,y:1,z:2},{x:2,y:2,z:2}],'x','y'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
对于那些你正在寻找类似的所有者,但没有布尔值作为过滤器的第一个属性,你可以做一个双groupby:
export function groupByLodash(results: myType[]) {
return mapValues(
groupBy(results, 'property.to.group'),
(result: myType) => groupBy(result, 'second.property.to.group'),
);
}
的结果应该类似于:
{
"property.to.group": { "second.property.to.group": {...result}}
}
在纯JS上对没有LODASH的对象或数组进行分组和过滤:
// Группировка и фильтрация объекта или массива без LODASH на чистом JS:
let k = "HUID", // group by;
input = [
{HUID:11,test:1},
{HUID:11,test:111},
{HUID:'eeeeeeeeeeee',test:11111},
{HUID:22,test:2},
{HUID:33,test:3}
],
result = input.reduce((map, obj) => {
//if(!obj.selected) { return map; }
let makeCode = (map[obj[k]] = map[obj[k]] || {}); // var modelCode = makeCode[obj.HUID] = makeCode[obj.HUID] || { count: 0 };
let l = map[obj[k]],
m = Object.keys(l).length;
l[m] = { ...obj };
return map;
}, {} );
console.log(result);
从VK复制
您不需要重复所有数组对象。使用loadash,您可以像下面这样做:
_.mapValues(_.groupBy(object, 'yourKeys'))
- AngularJS-使用'true'属性
- sails.js beforeCreate方法只接收required设置为true的模型属性
- 如何使函数将属性值从 FALSE 设置为 TRUE
- hasOwnProperty 在对照父对象属性进行检查时返回 true
- 为什么我的html节点保持类ng隐藏属性ng show=true
- 如何通过javarscript或jquery在数组中添加属性复选框(checked=true)
- AngularJS-为什么不;t替换:true使用templateUrl属性
- Image属性complete在实际渲染图像之前返回true
- 使用 javascript 更改 Gridview 文本框的可见属性 true 在下拉列表的选定索引更改事件上为 tru
- 为什么删除运算符返回 true,即使属性未从对象中删除
- 如何在骨干模型属性中设置布尔值true/false
- 如果返回true,则检查Javascript对象属性
- 使用jQuery将使用复选框的数据属性从false更改为true
- IE8 cloneNode(true)对象不支持此属性或方法
- 如果属性值为true,则按多个属性分组
- AngularJS ng重复筛选器:{visible:true}不遵循属性更改
- 即使没有显式指定属性,hasAttribute也应该返回true,但没有't
- 当javascript中checked属性设置为true时,复选框在UI中不会显示为checked
- 剑道分离器:如何改变“折叠”:false;拆分器属性为“可折叠”:true;点击按钮
- Rails link_to帮助器-提供onclick属性摆脱:remote =>true(动作作为HTML处理)