繁体   English   中英

如何对数组中的对象进行分组并根据 object 属性对其进行排序

[英]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 并将问题分组到某些组中。 在上面你可以看到我想出的部分代码。

关于如何对问题进行分组,我有许多条件。

  1. 任何小组的问题都不能少于两个。
  2. 'no-group'表示问题不在任何组中。 因此'no-group'可能只是一个问题或全部问题。
  3. 应在该组问题的最早日期之前分配组。 例如'group 1'最早(就日期而言)问题应早于“ group 2'中最早的问题,并且在重新组合问题或从组中删除问题时也应重新调整。
  4. 分组的问题可以重新分组。 这样做时,如果任何问题单独留在组中,则应标记为'no-group'
  5. 当使用'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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM