填充List <tuple <string,string>&gt;与linq

时间:2017-08-18 07:44:16

标签: c#

有一个像这样的字符串列表

{'123',
 '234',
 '345',
 '123c',
 '456',
 '234c'}

,任务是创建list<Tuple<string><string>> 并填充每个元组,使第一个值为'x',第二个值为'xc' 例如,Tuple&lt; 123,123c&gt; ,如果没有以'c'char结尾的对,只需将第二个值置为null,就像在元组Tuple&lt; 345,null&gt;中一样。有没有办法用linq做到这一点?。

4 个答案:

答案 0 :(得分:1)

您可以尝试这样的事情:

var result = list.GroupBy(word => !word.EndsWith('c'))
                 .Select(gr => Tuple.Create(gr.Key, gr.FirstOrDefault(i=>i.Contains(gr.Key))));

基本上,您可以根据列表元素进行分组,这些元素是否以字符“C&#39;”结尾。因此,您将拥有一系列键,这些键不会以字符“C&#39;”结尾。以及每个键的相关序列以及以&#39; c&#39;结尾的单词。然后按照元组的顺序投影结果,第一个元素是gropu的关键,第二个元素是以&#39; c&#39;结尾的相应值。如果它完全存在则为null,如果它不存在则为null。

答案 1 :(得分:1)

这是一个非常简单的解决方案,在分成两组后生成元组:

var firsts = strings.Where(s => !s.EndsWith("c"));
var seconds = strings.Where(s => s.EndsWith("c"));

var result = firsts.Select(f =>
    new Tuple<string, string>(f, seconds.FirstOrDefault(s => s.Replace("c", "") == f)));

将代码分为以下步骤,便于阅读和理解。

答案 2 :(得分:1)

您可以按删除尾随'c'的值对所有字符串进行分组,然后根据计数是否大于1来输出元组。

这是一个使用新的Tuple语法的C#7.x / .Net 4.7解决方案:

var result = strings
    .GroupBy(x => x.TrimEnd('c'))
    .Select((g, v) => (g.Key, g.Count() > 1 ? g.Key+'c': null));

使用旧版本的C#和.Net:

采用相同的方法
var result = strings
    .GroupBy(x => x.TrimEnd('c'))
    .Select((g, v) => Tuple.Create(g.Key, g.Count() > 1 ? g.Key+'c': null));

请注意,使用g.Count() > 1来确定序列是否包含多个元素通常不如使用g.Skip(1).Any()有效(除非基础序列是List或数组),但对于此特定应用程序将是高效的,因为集合中的项目从不超过2个。

答案 3 :(得分:0)

如果你的所有输入字符串都是一串数字,最后有一个可选的c,你可以试试这个:

var result = list.GroupBy(x => x.TrimEnd('c'))
                 .Select(g => Tuple.Create(g.Key, g.FirstOrDefault(v => v.EndsWith("c"))))

这将按数字字符串对它们进行分组,最后排除任何c,然后创建一个元组,其第一项是该数字字符串,其第二项是{{1如果它在列表中,则附加;如果没有,则附加c