Javascript 如何将数组中的对象分组并根据对象属性对其排序

Javascript 如何将数组中的对象分组并根据对象属性对其排序,javascript,arrays,recursion,Javascript,Arrays,Recursion,我正在尝试创建一个功能,用户可以调用该功能并将问题分组到特定的组中。上面您可以看到我提出的部分代码 我对如何分组问题有很多条件 任何小组的问题数量不得少于两个 'no-group'表示问题不在任何组中。因此,“无组”可以是一个问题,也可以是所有问题 小组应在该小组问题的最早日期前分配。例如,“第1组”最早的问题(就日期而言)应该早于“第2组”中最早的问题,当问题重新分组或从组中删除问题时,也应该重新调整 分组问题可以重新分组。这样做时,如果任何问题单独留在一个组中,则应将其标记为“无组” 当分配

我正在尝试创建一个功能,用户可以调用该功能并将问题分组到特定的组中。上面您可以看到我提出的部分代码

我对如何分组问题有很多条件

  • 任何小组的问题数量不得少于两个
  • 'no-group'
    表示问题不在任何组中。因此,
    “无组”
    可以是一个问题,也可以是所有问题
  • 小组应在该小组问题的最早日期前分配。例如,
    “第1组”
    最早的问题(就日期而言)应该早于“
    第2组”中最早的问题
    ,当问题重新分组或从组中删除问题时,也应该重新调整
  • 分组问题可以重新分组。这样做时,如果任何问题单独留在一个组中,则应将其标记为
    “无组”
  • 当分配组时,当采用
    'group1'
    时分配
    'group2'
    ,当采用
    'group2'
    时分配
    'group3'
    ,依此类推
  • 我的方法是使用if语句。但是,由于问题数组最多可以有20个问题,而且组可以从
    'group1'
    'group2'
    。。。对于
    'group20'
    ,if语句的数量将变多

    为了更好地沟通我想要实现的目标,我做出了一个决定。有没有一种方法可以使用递归来实现我想要实现的,并避免许多if语句

    如果有什么不清楚的地方,请询问我,我很乐意澄清

    stackblitz中的代码如下(这是一个角度stackblitz):

    控制器

     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
         */
     }
    
    观点:

      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
    
      }
    
    问题
    {{问题}
    {{问题组}
    分组选定的问题
    
    我担心评论中的讨论对我的理解没有多大帮助

    下面是一个仍在猜测您的一些需求的尝试:

    //实用程序函数
    constgroupby=(prop)=>(xs)=>
    减少(
    (a,{[prop]:p,…rest}=>({…a,[p]:[…(a[p]|[]),rest]}),
    {}
    )
    常量分区=(pred)=>(xs)=>
    x.reduce(([yes,no],x)=>pred(x)?[[…yes,x],no]:[yes,[…no,x]],[[],[],[])
    //主要功能
    const makeGroups=问题=>{
    const{'no-group':groupless,…rest}=groupBy('group')(问题)
    常量[largeEnough,tooSmall]=分区((v)=>v.length>1)(对象值(rest))
    const noGroup=[…groupless,…tooSmall.flat()].sort((a,b)=>a.date-b.date)
    返回{
    …对象。fromEntries(
    拉吉诺
    .map(group=>group.sort((a,b)=>a.date-b.date))
    .sort((组1,组2)=>group1[0]。日期-group2[0]。日期)
    .map((组,i)=>[`group${i+1}`,group])
    ),
    “无组”:无组
    }
    }
    //样本数据
    常量问题=[
    {{u id:1,q:'为什么?',组:'没有组',日期:'8',选择:false},
    {{u id:2,q:'what?',组:'A',日期:'6',选择:false},
    {{u id:3,q:'when?',group:'C',date:'7',selected:false},
    {{u id:4,q:'where?',group:'A',date:'5',selected:false},
    {{u id:5,q:'which?',组:'B',日期:'3',选择:false},
    {{u id:6,q:'who?',date:'0',selected:false},//没有提供任何组,因此将不在任何组中结束
    {{u id:7,q:'为什么不?',组:'B',日期:'9',选择:false},
    {{u id:8,q:'谁,我?',组:'A',日期:'4',选择:false},
    {{u id:9,q:'waldo在哪里?',组:'A',日期:'1',选择:false},
    {{u id:10,q:'哪条路是向上的?',组:'B',日期:'2',所选:false},
    {{u id:11,q:'什么时候吃午饭?',组:'D',日期:'10',所选内容:false},
    ];
    //演示
    console.log(生成组(问题))

    作为控制台包装{max height:100%!important;top:0}
    您应该使用
    lodash
    函数that@NinaScholz现在呢?我已经登录到我的stackblitz,这样链接可以在所有设备上运行。@NinaScholz我已经更新了我认为现在可以运行的问题。请尝试一下,让我知道它是否有。现在链接工作。谢谢,这工作。“有了这些,我就能实现我想要的。”YulePale:很高兴听到这个消息。请注意,在以后的问题中,如果您可以像我在这里所做的那样创建至少一个输入输出对,这将使人们更容易提供帮助。
    <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>