1

I have a class with the following properties:

public class Party
{
    public string Type { get; set; }
    public string Name { get; set; }
}

and this method to populate the list:

List<Party> parties = new List<Party>();
parties.Add(new Party {Type = "Plaintiff", Name = "Eilean Dover"});
parties.Add(new Party {Type = "Plaintiff", Name = "Bea O'Problem"});
parties.Add(new Party {Type = "Defendant", Name = "Anna Graham"});
parties.Add(new Party {Type = "Witness", Name = "John Doe"});
parties.Add(new Party {Type = "Witness", Name = "Rosa Shore"});

My goal is to put all the objects (parties) in a single string. So far, I have used String.Join and Linq in order to put them inline.

string partiesinline = string.Join(", ", parties.Select(x => String.Join(" ", new[] { x.Type, x.Name })));

After running this, the string partiesinline looks like this:

Plaintiff Eilean Dover, Plaintiff Bea O'Problem, Defendant Anna Graham, Witness John Doe, Witness Rosa Shore

My futher improvement is to group the parties by their type and put the type in a plural form if there are more of the same type. Ideally, the string should look like this:

Plaintiffs Eilean Dover, Bea O'Problem, Defendant Anna Graham and Witnesses John Doe, Rosa Shore

I could be using a Dictionary or a List in order to get the plurar of the Type but I am stuck in grouping the parties and retaining in the partiesinline string a single type for the parties having the same name. Do you have any suggestions with explanation?

I have read Using LINQ to group a list of objects and Using Linq to group a list of objects into a new grouped list of list of objects but I am stuck, I am unable to identify the steps in order to get the desired result.

Cosmin
  • 411
  • 4
  • 16

2 Answers2

1

You need multiple calls to string.Join. Consider:

  1. you want to combine the individual names for each group into one string per group,
  2. and then you want to combine the strings generated from each group into a single string.

The GroupBy method has an overload which lets you specify not just what you're grouping by:

party => party.Type

but the intermediate result for each group; in this case, a single string:

(type, group) => $"{type} {String.Join(", ", group.Select(party => party.Name))}"
  • type is what each group is grouped on (in this case the value in the Type property)
  • group is the grouped instances of Party, whose Name property we can project to a sequence of strings (group.Select(party => party.Name), which we can then join into a single string using String.Join.

Altogether:

var grouping = parties.GroupBy(
    party => party.Type,
    (type, group) => $"{type} {String.Join(", ", group.Select(party => party.Name))}"
);

grouping can now provide us with a sequence of strings, which we can use again with String.Join to create a single string:

var result = string.Join(",", grouping);

As for pluralizing the type, I think you could generally add an s, but put the exceptions to this rule inside a Dictionary<string, string>:

private static Dictionary<string, string> specialPlurals = new Dictionary<string, string> {
    {"Witness", "Witnesses"}
};

Then, write a function that would give you the appropriate plural:

public static string Pluralize(string singular) {
    if (string.IsNullOrWhiteSpace(singular)) { return singular;}
    if (specialPlurals.TryGetValue(singular, out var plural)) { return plural;}
    return $"{singular}s";
}

and use it as follows:

var grouping = parties.GroupBy(
    party => party.Type,
    (type, group) => $"{Pluralize(type)}: {String.Join(", ", group.Select(party => party.Name))}"
);
var result = string.Join("; ", grouping);

This generates the following:

Plaintiffs: Eilean Dover, Bea O'Problem; Defendants: Anna Graham; Witnesses: John Doe, Rosa Shore

.NET Fiddle

Zev Spitz
  • 13,950
  • 6
  • 64
  • 136
  • Although the answer Jamiec provided was enough for my tests, yours has the steps detailed and it is good documentation for further use. Thanks! – Cosmin Mar 26 '20 at 15:35
1

Given a dictionary where you can look up plurals:

Dictionary<string,string> plurals = new Dictionary<string,string>{
    ["Plaintiff"] = "Plaintiffs",
    ["Defendant"] = "Defendants",
    ["Witness"] = "Witnesses"
};

You could use this code:

var result = string.Join(", ", parties.GroupBy(x => x.Type).Select(item => {
    var prefix = item.Count()>1 ? plurals[item.Key] : item.Key;
    var people = String.Join(", ", item.Select(x => x.Name));
    return $"{prefix} {people}";
}));

Live example: https://dotnetfiddle.net/wCVgeB

Jamiec
  • 133,658
  • 13
  • 134
  • 193