代码之家  ›  专栏  ›  技术社区  ›  Chris McCall

合并两个列表的最简单方法

  •  1
  • Chris McCall  · 技术社区  · 14 年前

    我有两个 List<Name> S:

    public class Name
            {
                public string NameText {get;set;}
                public Gender Gender { get; set; }
            }
    
    public class Gender
            {
                public decimal MaleFrequency { get; set; }
                public decimal MaleCumulativeFrequency { get; set; }
                public decimal FemaleCumulativeFrequency { get; set; }
                public decimal FemaleFrequency { get; set; }
            }
    

    如果 NameText 属性匹配,我想 FemaleFrequency FemaleCumulativeFrequency 从女性名单中 Name S和 MaleFrequency MaleCumulativeFrequency 男性列表中的值 名字 创建一个列表 姓名 所有四个属性都已填充。

    在C中,使用.NET 3.5最简单的方法是什么?

    3 回复  |  直到 14 年前
        1
  •  5
  •   David Morton    14 年前

    合并列表时,是否尝试对每个值求和?如果是这样,请尝试如下操作:

    List<Name> list1 = new List<Name>();
    List<Name> list2 = new List<Name>();
    
    List<Name> result = list1.Union(list2).GroupBy(x => x.NameText).Select(x => new
    Name
    {
        NameText = x.Key,
        Gender = new Gender
        {
            FemaleCumulativeFrequency = x.Sum(y => y.Gender.FemaleCumulativeFrequency),
            FemaleFrequency = x.Sum(y => y.Gender.FemaleFrequency),
            MaleCumulativeFrequency = x.Sum(y => y.Gender.MaleCumulativeFrequency),
            MaleFrequency = x.Sum(y => y.Gender.MaleFrequency)
        }
    }).ToList();
    

    其作用如下:

    1. 合并列表,创建 IEnumerable<Name> 包含两个列表的内容。
    2. 按NameText属性对列表进行分组,因此,如果有同名的重复名称,它们将显示在同一组中。
    3. 选择一组新名称对象,对每个分组名称的属性求和…如果这更有意义,你也可以使用平均值。
    4. 将整个查询转换为 List<Name> 通过调用“tolist()”方法。

    编辑:或者,正如您在下面所说,您只想合并这两个列表…这样做:

    List<Name> allNames = femaleNames.Union(maleNames).ToList();
    
        2
  •  2
  •   Ian Mercer    14 年前

    这看起来很像人口普查名称频率数据,对吧?对于你所在的班级来说,性别有点用词不当,它更像是“频率数据”。

    实际上,您需要一个字典,这样您就可以查找任何名称并获得它的四个值。你可以简单地把男性带到字典上,然后对女性进行迭代,如果字典中有这个名字,替换它上面的女性概率,如果它不存在,创建一个新的字典条目。

    我自己处理相同数据的方法是在数据库中创建一个表,并附加所有四个值。

    下面是一些适用于您的方案的代码…

        Dictionary<string, Gender> result;
    
        result = males.ToDictionary(x => x.NameText, x => x.Gender);
        foreach (var female in females)
        {
            if (result.ContainsKey(female.NameText))
            {
                result[female.NameText].FemaleCumulativeFrequency = female.Gender.FemaleCumulativeFrequency;
                result[female.NameText].FemaleFrequency = female.Gender.FemaleFrequency;
            }
            else
                result.Add(female.NameText, female.Gender);
        }
    
        3
  •  1
  •   Lee    14 年前

    我认为这可能是你想要的,尽管我不确定它是否能像你预期的那样处理累积频率:

    var mergedNameList = maleNames
        .Concat(femaleNames)
        .GroupBy(n => n.NameText)
        .Select(nameGroup => new Name
        {
            NameText = nameGroup.Key,
            Gender = new Gender
            {
                MaleFrequency = nameGroup.Sum(n => n.Gender.MaleFrequency),
                MaleCumulativeFrequency = nameGroup.Sum(n => n.Gender.MaleCumulativeFrequency),
                FemaleFrequency = nameGroup.Sum(n => n.Gender.FemaleFrequency),
                FemaleCumulativeFrequency = nameGroup.Sum(n => n.Gender.FemaleCumulativeFrequency)
            }
        }.ToList();