[英]How to group objects in an array and sort them depending on an object property
groupSelectedQuestions(selectedQuestions){
var questions = [
{ q: 'why?', group: 'no-group', date: '1' },
{ q: 'what?', group: 'group 1', date: '1' },
{ q: 'when?', group: 'group 2', date: '2' },
{ q: 'where?', group: 'group 1', date: '2' },
{ q: 'which', group: 'group 2', date: '3' }
],
result = questions.reduce(function (r, a) {
r[a.group] = r[a.group] || [];
r[a.group].push(a);
return r;
}, {});
/**
more code here.
Here I would put if statements that check for all condtions
I have stated in the question below
*/
}
我正在尝试制作用户调用的 function 并将问题分组到某些组中。 在上面你可以看到我想出的部分代码。
关于如何对问题进行分组,我有许多条件。
'no-group'
表示问题不在任何组中。 因此'no-group'
可能只是一个问题或全部问题。'group 1'
最早(就日期而言)问题应早于“ group 2'
中最早的问题,并且在重新组合问题或从组中删除问题时也应重新调整。'no-group'
。'group 1'
分配组时,分配'group 2'
,当使用'group 2'
时分配'group 3'
,依此类推。 我会这样做的方式是使用 if 语句。 但是由于问题数组最多可以有二十个问题,并且组可以 go 从'group 1'
, 'group 2'
... 到'group 20'
,if 语句的数量会变得很多。
我做了一个堆栈闪电战来更好地传达我想要实现的目标。 有没有办法可以使用递归来实现我想要实现的目标并避免许多 if 语句?
如果有不清楚的地方,请询问我会很高兴说清楚。
stackblitz中的代码如下(它是一个Angular stackblitz):
controller
questions = [
{ _id:1, q: 'why?', group: 'no-group', date: '1', selected:false },
{ _id:2, q: 'what?', group: 'group 1', date: '1', selected:false },
{ _id:3, q: 'when?', group: 'group 2', date: '2', selected:false },
{ _id:4, q: 'where?', group: 'group 1', date: '2', selected:false },
{ _id:5, q: 'which?', group: 'group 2', date: '3', selected:false }
];
selectOrUnselectQuestion(question){
let newQuestions = this.questions.map(newQuestion => {
if(newQuestion._id === question._id){
if(!newQuestion.selected){
newQuestion.selected = true;
} else {
newQuestion.selected = false;
}
return newQuestion;
} else {
return newQuestion;
}
})
this.questions = newQuestions;
}
groupSelectedQuestions(){
let selectedQuestions = this.questions.filter(q => q.selected);
let selectedQuestionIds = selectedQuestions.map(selectedQuestion=>{ return selectedQuestion._id; })
let newQuestions = this.questions.map(question => {
if(selectedQuestions.length==1 && selectedQuestionIds.includes(question._id)){
question.group = 'no-group';
question.selected = false;
return question
} else
if(selectedQuestions.length>1 && selectedQuestionIds.includes(question._id)){
question.group = 'group 1';
question.selected = false;
return question
} else {
return question;
}
})
this.questions = newQuestions;
// deselect selected questions
}
风景:
<div style="text-align:center">Questions</div>
<div style="text-align:center; padding:10px;">
<div *ngFor="let question of questions" (click)="selectOrUnselectQuestion(question)"
[ngClass]="{'selected': question.selected}" class="question">
<span style="padding-right:10px">{{question.q}}</span>
<span>{{question.group}}</span>
</div>
<button (click)="groupSelectedQuestions()" style="margin:10px 0" type="button">
group selected questions
</button>
</div>
恐怕评论中的讨论对我理解没有太大帮助。
这是一个仍然猜测您的一些要求的尝试:
// utility functions const groupBy = (prop) => (xs) => xs.reduce ( (a, {[prop]: p, ...rest}) => ({...a, [p]: [...(a[p] || []), rest]}), {} ) const partition = (pred) => (xs) => xs.reduce (([yes, no], x) => pred (x)? [[...yes, x], no]: [yes, [...no, x]], [[], []]) // main function const makeGroups = questions => { const {'no-group': groupless, ...rest} = groupBy ('group') (questions) const [largeEnough, tooSmall] = partition ((v) => v.length > 1) (Object.values (rest)) const noGroup = [...groupless, ...tooSmall.flat()].sort((a, b) => a.date - b.date) return {...Object.fromEntries ( largeEnough.map (group => group.sort ((a, b) => a.date - b.date)).sort ((group1, group2) => group1 [0].date - group2 [0].date).map ((group, i) => [`group ${i + 1}`, group]) ), 'no-group': noGroup } } // sample data const questions = [ {_id: 1, q: 'why?', group: 'no-group', date: '8', selected: false }, {_id: 2, q: 'what?', group: 'A', date: '6', selected: false }, {_id: 3, q: 'when?', group: 'C', date: '7', selected: false }, {_id: 4, q: 'where?', group: 'A', date: '5', selected: false }, {_id: 5, q: 'which?', group: 'B', date: '3', selected: false }, {_id: 6, q: 'who?', date: '0', selected: false }, // no group supplied so will end up in no-group {_id: 7, q: 'why not?', group: 'B', date: '9', selected: false }, {_id: 8, q: 'who, me?', group: 'A', date: '4', selected: false }, {_id: 9, q: 'where is waldo?', group: 'A', date: '1', selected: false }, {_id: 10, q: 'which way is up?', group: 'B', date: '2', selected: false }, {_id: 11, q: 'when is lunch?', group: 'D', date: '10', selected: false }, ]; // demo console.log (makeGroups (questions))
.as-console-wrapper {max-height: 100%;important: top: 0}
output 将如下所示:
{
'group 1': [
{_id: 9, q: "where is waldo?", date: "1", selected: false},
{_id: 8, q: "who, me?", date: "4", selected: false},
{_id: 4, q: "where?", date: "5", selected: false},
{_id: 2, q: "what?", date: "6", selected: false}
],
'group 2': [
{_id: 10, q: "which way is up?", date: "2", selected: false},
{_id: 5, q: "which?", date: "3", selected: false},
{_id: 7, q: "why not?", date: "9", selected: false}
],
'no-group': [
{_id: 6, q: "who?", date: "0", selected: false},
{_id: 3, q: "when?", date: "7", selected: false},
{_id: 1, q: "why?", date: "8", selected: false},
{_id: 11, q: "when is lunch?", date: "10",selected: false}
]
}
这些组在内部按日期排序,并且这些组按列表中的第一个日期在它们之间排序。 任何没有至少两个条目的组都被折叠成no-group
,并且按顺序分配组号。
最大的问题是这是否符合您的需求。 如果没有,您能否像我在这里所做的那样显示示例输入和预期的 output?
尽管我是辅助函数的忠实拥护者,并且我偶尔会使用该partition
以及该groupBy
的稍微通用的版本,但我想指出,由于每个仅使用一次,我们可以非常简单地内联它们:
const makeGroups = questions => {
const {'no-group': groupless, ...rest} = questions .reduce (
(a, {group = 'no-group', ...rest}) => ({...a, [group]: [...(a[group] || []), rest]}),
{}
)
const [largeEnough, tooSmall] = Object .values (rest) .reduce (
([yes, no], x) => x.length > 1 ? [[...yes, x], no] : [yes, [...no, x]], [[], []]
)
const noGroup = [...groupless, ...tooSmall.flat()].sort((a, b) => a.date - b.date)
return {
...Object .fromEntries (
largeEnough
.map (group => group.sort ((a, b) => a .date - b .date))
.sort ((group1, group2) => group1 [0] .date - group2 [0] .date)
.map ((group, i) => [`group ${i + 1}`, group])
),
'no-group': noGroup
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.