tags:

views:

139

answers:

3

I've got two 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; }
        }

If the NameText property matches, I'd like to take the FemaleFrequency and FemaleCumulativeFrequency from the list of female Names and the MaleFrequency and MaleCumulativeFrequency values from the list of male Names and create one list of Names with all four properties populated.

What's the easiest way to go about this in C# using .Net 3.5?

+5  A: 

Are you attempting to sum each of the values when you merge the lists? If so, try something like this:

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();

What this does is the following:

  1. Unions the lists, creating an IEnumerable<Name> that contains the contents of both lists.
  2. Groups the lists by the NameText property, so if there are duplicate Names with the same NameText, they'll show up in the same group.
  3. Selects a set of new Name objects, with each grouped Name's properties summed... you can also use Average if that makes more sense.
  4. Converts the entire query to a List<Name> by calling the "ToList()" method.

Edit: Or, as you've said below, you simply want to merge the two lists... do this:

List<Name> allNames = femaleNames.Union(maleNames).ToList();
David Morton
no, not summing them, I've got one list of female names and one list of male names. I want one list of names with all four properties filled out. Each list will only have its gender's frequencies, I need both attached to each name
Chris McCall
however, this is a very good start, thanks
Chris McCall
Ahhh... I see... See my edit above.
David Morton
this is what I ended up using and it's great. Thanks!
Chris McCall
A: 

I think this could be what you want although I'm not sure if it handles the cumulative frequencies as you'd expect:

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();
Lee
+1  A: 

This looks a lot like the census name frequency data, right? Gender is a bit of a misnomer for the class you have it's more like "FrequencyData".

In effect you want a Dictionary so you can lookup any name and get the four values for it. You could simply take the males and do ToDictionary(...) on it and then iterate over the females, if the name exists in the dictionary, replace the female probabilities on it, if it doesn't exist, create a new dictionary entry.

My own approach to this same data was to create a Table in a database with all four values attached.

Here's some code for your scenario ...

    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);
    }
Hightechrider