LINQ list to sentence format (insert commas & “and

2020-03-20 12:36发布

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, or something that will output the names in sentence format using commas and "ands".

{1, John}
{2, Mark}
{3, George}

to

"1:John, 2:Mark and 3:George"

I'm fine with hardcoding the ID + ":" + Name part, but it could be a ToString() depending on the type of the linq query result. I'm just wondering if there is a neat way to do this with linq or String.Format().

标签: c# linq string
17条回答
Root(大扎)
2楼-- · 2020-03-20 13:03

This can be the way you can achieve your goal

var list = new[] { new { ID = 1, Name = "John" }, 
                   new { ID = 2, Name = "Mark" }, 
                   new { ID = 3, Name = "George" }
                 }.ToList();

int i = 0;

string str = string.Empty;

var k = list.Select(x => x.ID.ToString() + ":" + x.Name + ", ").ToList();

k.ForEach(a => { if (i < k.Count() - 1) { str = str +  a; } else { str = str.Substring(0, str.Length -2) + " and " + a.Replace("," , ""); } i++; });
查看更多
Luminary・发光体
3楼-- · 2020-03-20 13:04

Why Linq?

StringBuilder sb = new StringBuilder();

for(int i=0;i<k.Count();i++)
{
   sb.Append(String.Format("{0}:{1}", k[i].ID, k[i].Name);
   if(i + 2 < k.Count())
      sb.Append(", ");
   else if(i + 1 < k.Count())
      sb.Append(" and ");
}

Really, all Linq will let you do is hide the loop.

Also, make sure you do or do not want the "Oxford Comma"; this algorithm will not insert one, but a small change will (append the comma and space after every element except the last, and also append "and " after the next-to-last).

查看更多
Evening l夕情丶
4楼-- · 2020-03-20 13:06

Just for fun, here’s something that really uses functional LINQ — no loop and no StringBuilder. Of course, it’s pretty slow.

var list = new[] { new { ID = 1, Name = "John" },
                   new { ID = 2, Name = "Mark" },
                   new { ID = 3, Name = "George" } };

var resultAggr = list
    .Select(item => item.ID + ":" + item.Name)
    .Aggregate(new { Sofar = "", Next = (string) null },
               (agg, next) => new { Sofar = agg.Next == null ? "" :
                                            agg.Sofar == "" ? agg.Next :
                                            agg.Sofar + ", " + agg.Next,
                                    Next = next });
var result = resultAggr.Sofar == "" ? resultAggr.Next :
             resultAggr.Sofar + " and " + resultAggr.Next;

// Prints 1:John, 2:Mark and 3:George
Console.WriteLine(result);
查看更多
Lonely孤独者°
5楼-- · 2020-03-20 13:06

Y'all are making it too complicated:

var list = k.Select(x => x.ID + ":" + x.Name).ToList();
var str = list.LastOrDefault();
str = (list.Count >= 2 ? list[list.Count - 2] + " and " : null) + str;
str = string.Join(", ", list.Take(list.Count - 2).Concat(new[]{str}));
查看更多
我想做一个坏孩纸
6楼-- · 2020-03-20 13:06

How about this?

var k = people.Select(x=>new{x.ID, x.Name});
var stringified = people
                  .Select(x => string.Format("{0} : {1}", x.ID, x.Name))
                  .ToList();
return string.Join(", ", stringified.Take(stringified.Count-1).ToArray())
       + " and " + stringified.Last();
查看更多
何必那么认真
7楼-- · 2020-03-20 13:07

There are ways to optimize this since it isn't very efficient, but something like this may work:

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

var last = k.Last();
k.Aggregate(new StringBuilder(), (sentence, item) => { 
    if (sentence.Length > 0)
    {
        if (item == last)
            sentence.Append(" and ");
        else
            sentence.Append(", ");
    }

    sentence.Append(item.ID).Append(":").Append(item.Name);
    return sentence;
});
查看更多
登录 后发表回答