LINQ list to sentence format (insert commas & “and”)

后端 未结 17 1392
天命终不由人
天命终不由人 2021-01-12 23:33

I have a linq query that does something simple like:

var k = people.Select(x=>new{x.ID, x.Name});

I then want a function or linq lambda,

17条回答
  •  南方客
    南方客 (楼主)
    2021-01-13 00:34

    StringBuilder Approach

    Here's an Aggregate with a StringBuilder. There's some position determinations that are made to clean up the string and insert the "and" but it's all done at the StringBuilder level.

    var people = new[]
    {
        new { Id = 1, Name = "John" },
        new { Id = 2, Name = "Mark" },
        new { Id = 3, Name = "George" }
    };
    
    var sb = people.Aggregate(new StringBuilder(),
                 (s, p) => s.AppendFormat("{0}:{1}, ", p.Id, p.Name));
    sb.Remove(sb.Length - 2, 2); // remove the trailing comma and space
    
    var last = people.Last();
    // index to last comma (-2 accounts for ":" and space prior to last name)
    int indexComma = sb.Length - last.Id.ToString().Length - last.Name.Length - 2;
    
    sb.Remove(indexComma - 1, 1); // remove last comma between last 2 names
    sb.Insert(indexComma, "and ");
    
    // 1:John, 2:Mark and 3:George
    Console.WriteLine(sb.ToString());
    

    A String.Join approach could have been used instead but the "and" insertion and comma removal would generate ~2 new strings.


    Regex Approach

    Here's another approach using regex that is quite understandable (nothing too cryptic).

    var people = new[]
    {
        new { Id = 1, Name = "John" },
        new { Id = 2, Name = "Mark" },
        new { Id = 3, Name = "George" }
    };
    var joined = String.Join(", ", people.Select(p => p.Id + ":" + p.Name).ToArray());
    Regex rx = new Regex(", ", RegexOptions.RightToLeft);
    string result = rx.Replace(joined, " and ", 1); // make 1 replacement only
    Console.WriteLine(result);
    

    The pattern is simply ", ". The magic lies in the RegexOptions.RightToLeft which makes the match occur from the right and thereby makes the replacement occur at the last comma occurrence. There is no static Regex method that accepts the number of replacements with the RegexOptions, hence the instance usage.

提交回复
热议问题