我可以按元素属性将列表拆分为更小的列表吗

Posted

技术标签:

【中文标题】我可以按元素属性将列表拆分为更小的列表吗【英文标题】:Can i split a List by element property into smaller lists 【发布时间】:2021-07-04 04:46:51 【问题描述】:

我有一个庞大的调查答案列表,无论是谁,它们都聚集在一起,我已按回答者的 ID 对列表进行分组,但现在我需要将此列表拆分为较小的列表,其中只有一个人的答案。

我现在的大列表称为“surveyAnswers.Respostas”,每个单独的答案都是“SurveyAnswer”,并且人员 ID 的属性是“quemRespondeu”

我将列表分组如下:“surveyAnswers.Respostas.GroupBy(x => x.quemRespondeu)”

如何创建一个包含来自单个人员 ID 的所有答案的列表??

提前谢谢各位!!

【问题讨论】:

不确定我是否完全理解这个问题,但似乎以下内容应该可以解决问题:surveyAnswers.Respostas.Where(x => x.PersonId == yourSinglePersonId) 【参考方案1】:

以下是获取字典的方法,其中键是人员 ID,值是相应人员所有答案的列表:

var grouped = . . .GroupedBy(x => x.quemRespondeu);            //the result you have already

var listByRespondeu = grouped.ToDictionary(g => g.Key, g => g.ToList());    //answers by person id

【讨论】:

【参考方案2】:

也许您不需要先进行分组,但我不能保证对抗 Linq 的性能会更好。实际上 Linq 代码更简单,这通常是非常需要的。无论如何,为了完成,假设 quemRespondeu 是 long 类型:


public  Dictionary<long,List<string>> GroupAnswers(List<Answer> AllAnswers)
        
            long[] allIds = new long[AllAnswers.Count];
            Answer[] AllAnswersArray = AllAnswers.ToArray();

            for (int i = 0; i < AllAnswers.Count; i++)
                allIds[i] = AllAnswers[i].quemRespondeu;

            Array.Sort(allIds, AllAnswersArray);

            Dictionary<long, List<string>> DictAllAnswersGrouped = new Dictionary<long, List<string>>();
            List<string> ListCurrentUser = null;

            long prevId = allIds[0] - 1;//to assure that ListCurrentUser is initialized in the first iteration 
            for (int i=0; i< allIds.Length; i++)
            
                long Id = allIds[i];
                if(Id!=prevId)
                
                    ListCurrentUser = new List<string>();
                    DictAllAnswersGrouped.Add(Id, ListCurrentUser);
                    prevId = Id;
                

                ListCurrentUser.Add(AllAnswersArray[i].SurveyAnswer);
            

            return DictAllAnswersGrouped;
        

然后你会调用:

  Dictionary<long,List<string>> GroupedAnswersDict = GroupAnswers(surveyAnswers.Respostas);
  
  long user_XId = 10; //whatever you need
  List<string> userX_Answers;
   if (!GroupedAnswersDict.TryGetValue(userX_Id, out userX_Answers))
         userX_Answers = null;

免责声明: 正如我所说,Linq 代码更简单易读,因此在大多数情况下它应该是首选。尽管如此,在某些特定情况下可以选择上面的代码,例如,如果需要一些更复杂的功能,如果 Linq 不能使用,或者它对性能有任何实际好处。

实际上,出于好奇,我做了一个小测试,看看它的性能如何,并且在没有进一步优化的情况下,Linq 的性能通常优于这个算法(大约 2 倍),甚至将它与完全等效的算法进行比较:

   var grouped = surveyAnswers.Respostas.GroupBy(x => x.quemRespondeu);       
   Dictionary<long, List<string>> GroupedAnswersDict =
              grouped.ToDictionary(g => g.Key, g => g.Select(l => l.SurveyAnswer).ToList());

仅在每个用户的答案数量与用户数量相比非常少的情况下,该算法的性能优于上面的 Linq 代码(小于 1.2 倍),但仍然比分类分组慢(由 Supa 发布在这里,归功于他):

   var grouped = surveyAnswers.Respostas.GroupBy(x => x.quemRespondeu);       
   Dictionary<long, List<Answer>> GroupedAnswersDict = 
                     grouped.ToDictionary(g => g.Key, g => g.ToList());

所以在这种情况下,性能也不是选择它而不是 Linq 的理由。

【讨论】:

这与上一个答案基本相同,但用几十行代码而不是一行代码:) ***.com/a/67002410/5714954 当然,我发布了完成代码,也是因为我对性能有疑问。但我刚刚进行了一些测试,Linq 明显优于这段代码,所以我更新了我的答案以明确

以上是关于我可以按元素属性将列表拆分为更小的列表吗的主要内容,如果未能解决你的问题,请参考以下文章

如何将结果集拆分为更小的子集?

RxSwift - 将序列拆分为更小的序列以连接

如何使用 JavaScript 将长数组拆分为更小的数组

将多维数组拆分为更小的数组

putExtra:我应该如何处理大型数组?数据库或拆分为更小的阵列?

如何使用JavaScript将长数组拆分为更小的数组