如何在 Linq 中删除组查询的重复数据

本文关键字:查询 数据 删除 Linq | 更新日期: 2023-09-27 18:37:24

我试图找到与每个错误相关的文件名的不同列表,我使用 linq 对与每个错误 id 相关的所有文件名进行分组。我不知道如何删除与每个bugid相关的重复文件名,在文件输出中,我有这样的多行: 错误 ID 文件名 1 文件名 2 文件名 3 文件名 4 ............. 有多个行具有相同的错误 ID,并且每个错误 ID 也有重复的文件名, 这是我的代码:

using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;

namespace finalgroupquery
{
    class MainClass
{
        public static void Main (string[] args)
        {
            List <bug> list2=new List <bug> ();
             using(System.IO.StreamReader reader1= new System.IO.StreamReader( @"/home/output"))
                using (System.IO.StreamWriter file = new System.IO.StreamWriter( @"/home/output1")) 
                        {string line1;
                         while ((line1=reader1.ReadLine())!=null) 
                            { string[] items1=line1.Split(''t');        
                                    bug bg=new bug();
                                      bg.bugid=items1[0];
                                for (int i=1; i<=items1.Length -1;i++)
                                    { bg.list1.Add(items1[i]);}
                                            list2.Add(bg);
                            }
                            var bugquery= from c in list2 group c by c.bugid into x select
                                            new Container { BugID = x.Key, Grouped = x };

                            foreach (Container con in bugquery)
                            {
                                StringBuilder files = new StringBuilder();
                                files.Append(con.BugID);
                                files.Append("'t");
                                foreach(var x in con.Grouped)
                                {
                                    files.Append(string.Join("'t", x.list1.ToArray()));
                                }
                                file.WriteLine(files.ToString());       }

            }
        }
    }
    public class Container
    {
        public string BugID {get;set;}
        public IGrouping<string, bug> Grouped {get;set;}
    }
    public class bug
    { 
        public List<string> list1{get; set;}
        public string bugid{get; set;}
        public bug()
        {
            list1=new List<string>();
        }       

    }
}

}

如何在 Linq 中删除组查询的重复数据

从您的描述中,听起来您想这样做:

        List <bug> bugs = new List<bug>();
        var lines = System.IO.File.ReadLines(@"/home/bugs");
        foreach (var line in lines) {
            string[] items = line.Split(''t');
            bug bg=new bug();
            bg.bugid = items[0];
            bg.list1 = items.Skip(1).OrderBy(f => f).Distinct().ToList();
            bugs.Add(bg);
            }

这将生成一个对象列表,其中每个对象都有一个唯一的文件名列表。

尝试使用此代码:

        var bugquery = from c in list2
                        group c by c.bugid into x
                        select new bug { bugid = x.Key, list1 = x.SelectMany(l => l.list1).Distinct().ToList() };
        foreach (bug bug in bugquery)
        {
            StringBuilder files = new StringBuilder();
            files.Append(bug.bugid);
            files.Append("'t");
            files.Append(string.Join("'t", bug.list1.ToArray()));
            file.WriteLine(files.ToString());
        }

由于 SelectManyDistinct Linq 运算符的组合,您可以平展文件名列表并删除单行中的重复项。

SelectMany (来自 msdn):

将序列的每个元素投影到 IEnumerable 并展平 将生成的序列合并为一个序列。

不同

(与 msdn 不同):

返回序列中的不同元素。

这也意味着不再需要您的Container类,因为不再需要循环访问IGrouping<string, bug>集合(此处list1包含所有与错误相关的文件名,没有重复项)。

编辑

由于在读取和解析文件后可能有一些空行和/或空字符串,因此您可以使用此代码来摆脱它们:

        using (System.IO.StreamReader reader1 = new System.IO.StreamReader(@"/home/sunshine40270/mine/projects/interaction2/fasil-data/common history/outputpure"))
        {
            string line1;
            while ((line1 = reader1.ReadLine()) != null)
            {
                if (!string.IsNullOrWhiteSpace(line1))
                {
                    string[] items1 = line1.Split(new [] { ''t' }, StringSplitOptions.RemoveEmptyEntries);
                    bug bg = new bug();
                    bg.bugid = items1[0];
                    for (int i = 1; i <= items1.Length - 1; i++)
                    {
                        bg.list1.Add(items1[i]);
                    }
                    list2.Add(bg);
                }
            }
        }

您会注意到:

  • 存储在line1中的新行一旦从流中检索到,就会立即检查它们的空性(带有!string.IsNullOrWhiteSpace(line1)
  • 若要从 string.Split 方法的返回值中省略空子字符串,可以使用 StringSplitOptions.RemoveEmptyEntries 参数。

希望这有帮助。