Underscore.js groupBy 两级
Underscore.js groupBy two levels
我似乎无法正确表达这一点,因为我需要按 date
和 foo
:
分组
// Using date as numbers for clear example
// date key should be grouped into a key
// Under that key (date), I should see another key of "foo"
let list = [
{ date: "1", foo: "me", result: "meFoo"},
{ date: "1", foo: "me2", result: "meYou"},
{ date: "1", foo: "me3", result: "meHe"},
{ date: "2", foo: "me", result: "meHim"},
{ date: "2", foo: "me2", result: "meHim"}
]
let grouped = _.groupBy(list, "date") // keys ie 1, 2
// I need another key under the date key, possible?
let grouped = _.groupBy(list, "date", (val) => _.groupBy(val), "foo") // result not expected
这里有点复杂,所以我使用下划线来简化复杂性。这可能吗?
然后我会做类似的事情,我可以使用 _.pluck
:
Object.keys(grouped).map( dateKey => Object.keys(grouped[dateKey]).map(fooKey => console.log( grouped[dateKey][fookey][0] )) )
从最高层看确实不对。
预期结果类似于:
DATE // key
|
|___ FOO // key
|
|__ array foo objects
这将为您提供所需的数组。
_.map(_.groupBy(list, 'date'), (value, key) => ({[key]: _.groupBy(value, 'foo')}))
希望你想要这样的结果:
var list = [{ date: "1", foo: "me", result: "meFoo" }, { date: "1", foo: "me2", result: "meYou" }, { date: "1", foo: "me3", result: "meHe" }, { date: "2", foo: "me", result: "meHim" }, { date: "2", foo: "me2", result: "meHim" }],
grouped = _.map(_.groupBy(list, 'date'), (value, key) => ({[key]: _.groupBy(value, 'foo')}));
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
功能性(使用 reduce):
list.reduce((acc, item) => {
const key1 = item.date
const group1 = acc[key1] || {}
const key2 = item.foo
const group2 = group1[key2] || []
return {
...acc,
[key1]: {
...group1,
[key2]: group2.concat(item)
}
}
}, {})
程序:
let grouped = {}
list.forEach((item) => {
// Create an empty object if this key has not already been set:
grouped[item.date] = grouped[item.date] || {}
// Create an empty list if this key has not already been set:
grouped[item.date][item.foo] = grouped[item.date][item.foo] || []
// Push the item to our group:
grouped[item.date][item.foo].push(item)
})
在 python 中,这将是:
from collections import defaultdict
_list = [
{"date":"1","foo":"me","result":"meFoo"},
{"date":"1","foo":"me2","result":"meYou"},
{"date":"1","foo":"me3","result":"meHe"},
{"date":"2","foo":"me","result":"meHim"},
{"date":"2","foo":"me2","result":"meHim"}
]
grouped = defaultdict(lambda: defaultdict(list))
for item in _list:
grouped[item['date']][item['foo']].append(item)
这是使用 function
组合实现此目的的另一种方法。为此,我使用了 Ramda 库。首先,通过日期对其进行分组,然后通过 foo 对其进行分组。另外请注意,我没有找到任何用于迭代对象键的柯里化函数,这就是我自己添加它的原因。
let list = [
{ date: "1", foo: "me", result: "meFoo"},
{ date: "1", foo: "me2", result: "meYou"},
{ date: "1", foo: "me3", result: "meHe"},
{ date: "2", foo: "me", result: "meHim"},
{ date: "2", foo: "me2", result: "meHim"},
{ date: "2", foo: "me2", result: "meHimAnother"}
]
function iterKeys(fn) {
return function(obj) {
for (var key in obj) {
obj[key] = fn(obj[key])
}
return obj;
}
}
var group = R.compose(iterKeys(R.groupBy(R.prop('foo'))), R.groupBy(R.prop('date')))
console.log(group(list));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
你快到了。对于第二级分组,您需要映射第一级分组的值:
let result = _.chain(list)
.groupBy('date')
.mapObject( grp => _.groupBy(grp, 'foo'))
.value();
我似乎无法正确表达这一点,因为我需要按 date
和 foo
:
// Using date as numbers for clear example
// date key should be grouped into a key
// Under that key (date), I should see another key of "foo"
let list = [
{ date: "1", foo: "me", result: "meFoo"},
{ date: "1", foo: "me2", result: "meYou"},
{ date: "1", foo: "me3", result: "meHe"},
{ date: "2", foo: "me", result: "meHim"},
{ date: "2", foo: "me2", result: "meHim"}
]
let grouped = _.groupBy(list, "date") // keys ie 1, 2
// I need another key under the date key, possible?
let grouped = _.groupBy(list, "date", (val) => _.groupBy(val), "foo") // result not expected
这里有点复杂,所以我使用下划线来简化复杂性。这可能吗?
然后我会做类似的事情,我可以使用 _.pluck
:
Object.keys(grouped).map( dateKey => Object.keys(grouped[dateKey]).map(fooKey => console.log( grouped[dateKey][fookey][0] )) )
从最高层看确实不对。
预期结果类似于:
DATE // key
|
|___ FOO // key
|
|__ array foo objects
这将为您提供所需的数组。
_.map(_.groupBy(list, 'date'), (value, key) => ({[key]: _.groupBy(value, 'foo')}))
希望你想要这样的结果:
var list = [{ date: "1", foo: "me", result: "meFoo" }, { date: "1", foo: "me2", result: "meYou" }, { date: "1", foo: "me3", result: "meHe" }, { date: "2", foo: "me", result: "meHim" }, { date: "2", foo: "me2", result: "meHim" }],
grouped = _.map(_.groupBy(list, 'date'), (value, key) => ({[key]: _.groupBy(value, 'foo')}));
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
功能性(使用 reduce):
list.reduce((acc, item) => {
const key1 = item.date
const group1 = acc[key1] || {}
const key2 = item.foo
const group2 = group1[key2] || []
return {
...acc,
[key1]: {
...group1,
[key2]: group2.concat(item)
}
}
}, {})
程序:
let grouped = {}
list.forEach((item) => {
// Create an empty object if this key has not already been set:
grouped[item.date] = grouped[item.date] || {}
// Create an empty list if this key has not already been set:
grouped[item.date][item.foo] = grouped[item.date][item.foo] || []
// Push the item to our group:
grouped[item.date][item.foo].push(item)
})
在 python 中,这将是:
from collections import defaultdict
_list = [
{"date":"1","foo":"me","result":"meFoo"},
{"date":"1","foo":"me2","result":"meYou"},
{"date":"1","foo":"me3","result":"meHe"},
{"date":"2","foo":"me","result":"meHim"},
{"date":"2","foo":"me2","result":"meHim"}
]
grouped = defaultdict(lambda: defaultdict(list))
for item in _list:
grouped[item['date']][item['foo']].append(item)
这是使用 function
组合实现此目的的另一种方法。为此,我使用了 Ramda 库。首先,通过日期对其进行分组,然后通过 foo 对其进行分组。另外请注意,我没有找到任何用于迭代对象键的柯里化函数,这就是我自己添加它的原因。
let list = [
{ date: "1", foo: "me", result: "meFoo"},
{ date: "1", foo: "me2", result: "meYou"},
{ date: "1", foo: "me3", result: "meHe"},
{ date: "2", foo: "me", result: "meHim"},
{ date: "2", foo: "me2", result: "meHim"},
{ date: "2", foo: "me2", result: "meHimAnother"}
]
function iterKeys(fn) {
return function(obj) {
for (var key in obj) {
obj[key] = fn(obj[key])
}
return obj;
}
}
var group = R.compose(iterKeys(R.groupBy(R.prop('foo'))), R.groupBy(R.prop('date')))
console.log(group(list));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
你快到了。对于第二级分组,您需要映射第一级分组的值:
let result = _.chain(list)
.groupBy('date')
.mapObject( grp => _.groupBy(grp, 'foo'))
.value();