【问题标题】:How do I find duplicate sequential entries in a Generic List in C#?如何在 C# 的通用列表中找到重复的顺序条目?
【发布时间】:2011-06-12 01:29:11
【问题描述】:

我有一些要处理的标记文件。

文件中的每一行都具有以下格式(为清晰起见进行了格式化):

Name1     Tag1     Origin1  
Name2     Tag2     Origin2  

我需要一个执行以下操作的 C# 解决方案:

  1. 获取名称出现的标记、来源和行号。
  2. 查看两个或多个连续名称是否具有相同的标签。如果是这样,请将它们组合起来。

为了做到这一点,我尝试了以下代码:

var line_token = new List<object_tag>();
line_token.Add(new object_tag 
{ file_name = filename, 
  line_num = line_number, 
  string_name = name, 
  string_tag = tag, 
  string_origin = origin
});

ListArrayList 获取其输入值。

示例输入:

item[0]:  
file_name:"test1.txt"  
line_num:1  
string_name:Asia  
string_tag:NP  
string_origin:<unknown>

有没有办法根据string_tag 搜索此列表,并查找一行中的两个或多个项目是否具有相同的 string_tag,如果是,则将它们组合成一个新项目?


更新:让我发布一些代码以使问题更清楚..

我用这个创建文件列表..

 private  static List <object_tag> tagged_line_list()
    {
        string input = "C:Desktop\\_tagged\\";
        string line;
        string[] files;
        
        int j = 0;
        

        if (System.IO.Directory.Exists(input) == false)
        {

            Console.WriteLine("The file doesn't exist");
        }
        //take the folder's files
        files = System.IO.Directory.GetFiles(input);
        //create new list with type object_tag
        var line_token = new List<object_tag>();
        //delete the contents of the list
        line_token.Clear();

        //create an array list 
        ArrayList tokens = new ArrayList();
        tokens.Clear();

        foreach (string file in files)
        {
            string filename = System.IO.Path.GetFileNameWithoutExtension(file);
            int line_number = 1;
            //read the files
            StreamReader sr = new StreamReader(file);

            while ((line = sr.ReadLine()) != null)
            {
                string input_line = line;
                char[] delimiters = { '\t' };
                //split the line in words
                string[] words = input_line.Split(delimiters);
                //add each word to the token array_list
                foreach (string word in words)
                {
                    tokens.Add(word);
                }

                string name = tokens[j+ 0] as string;
                string tag = tokens[j + 1] as string;
                string origin = tokens[j + 2] as string;

               //add to the line-token list instances
                line_token.Add(new object_tag{file_name=filename,line_num=line_number,string_name=name,string_tag=tag,string_origin=origin});
                
                j = j + 3; 
                line_number++;
            }
           
            sr.Close();
        }
        //returns the line_token list
        return line_token;   
    }

接下来我要搜索的代码列表是

private static List<object_tag> search_list()
    {
        //calls the tagged_line_list method for retrieving the line-token list
        var line_token = tagged_line_list();
        object_tag last = null;
        List<object_tag> du_np = new List<object_tag>();
        du_np.Clear();
        List<object_tag> list_np_query = new List<object_tag>();
        list_np_query.Clear();


          var np_query =
            from i in line_token
            where ((i.string_tag == "NP" | i.string_tag == "NPS"))
            select i;
        //create new list which contains instances with string_tag NP or NPS
          list_np_query = np_query.ToList<object_tag>();

          for (int i = 0; i < list_np_query.Count; i++)
          {
              if (last == null)
              {
                  last = list_np_query[i];

              }
              else if (
                  //the objects are in the same file
                  (last.file_name == list_np_query[i].file_name)
                  &
                  //the objects are consecutive
                  (list_np_query[i].line_num - last.line_num == 1)

                  )
              {


                  last.file_name = list_np_query[i - 1].file_name;
                  last.line_num = list_np_query[i - 1].line_num;
                  last.string_name = last.string_name + " " + list_np_query[i].string_name;
                  last.string_tag = list_np_query[i - 1].string_tag;
                  last.string_origin = "<unknown>";

                  du_np.Add(last);

              }
              else
              {
                  last = list_np_query[i];

              }
          }

            return (du_np);
    }

      

 

现在我有一个名为 list_np_query 的列表,其中仅包含带有 string_tag NP 或 NPS 的对象。如果对象在连续的行中并且具有相同的文件名,我会将它们放在一个名为du_np 的新列表中。解决方案就在我面前,但我看不到它...... 无论如何,感谢大家的帮助和时间!!!!!

【问题讨论】:

  • 请定义合并。因为即使标签相同,名称和来源也不同。另外我假设您必须继续组合,直到没有要组合的记录,例如连续5条相同标签的记录应合并为1条。
  • 你能把你喜欢的答案之一标记为正确的吗?

标签: c# linq list


【解决方案1】:

你能用字典来表示这个吗?字典可让您根据非数字值跟踪信息。不过,我不确定这是否适合您的应用程序。

var items = new Dictionary<string, object_tag>();

foreach(item in itemArray)
{
    if(items.ContainsKey(item.string_tag))
    {
        //do your combining stuff and store in items[item.string_tag]
    }
    else
    {
        items.add(item.string_tag, new object_tag{/*blablablah*/});
    }
}

【讨论】:

  • 谢谢...我试一试..看看结果..我认为列表最容易处理..
【解决方案2】:

您还可以编写一个 for 循环,向前看,并在项目满足您的需求时返回。喜欢:

IEnumerable<object_tag> CombineDuplicates(ArrayList source)
{
  object_tag last = null;
  for (int i=0;i<source.Count;i++)
  {
   if (last == null) 
   {
     last = source[i];
   }
   else if (last.string_tag == source[i].string_tag)
   {
      last.Combine(source[i]);
   }
   else 
   {
      yield return last;
      last = source[i];
   }
  }
  yield return last;
}

然后就可以调用了

foreach (var item in CombineDuplicates(input))
{
   //do whatever you want
}

并不是说它是唯一的解决方案,但 C# 有很多口味...... :) (您可以用列表替换 IEnumerable,在函数开头创建一个新列表,而不是生成它们,您可以将它们添加到列表中,并在最后返回列表。选择更适合您需要的列表。 ..)

【讨论】:

    【解决方案3】:

    如果“合并”是指删除重复记录,那么我有一个 linq 解决方案适合你。

    var results =
        (from lt in line_token
        orderby lt.line_num
        group lt by lt.string_tag into glts
        let dups = glts
            .Skip(1)
            .Zip(glts, (lt1, lt0) => new
                {
                    lt1,
                    delta = lt1.line_num - lt0.line_num
                })
            .Where(x => x.delta == 1)
            .Select(x => x.lt1)
        select glts.Except(dups))
            .SelectMany(x => x)
            .OrderBy(x => x.line_num);
    

    它并不完全漂亮,但它确实有效。

    【讨论】:

      【解决方案4】:

      我会使用列表,在这里你可以将许多变量传递给这个部分。例如,例如;

       list<string, int> item = new list()<string,int>;
      

      然后您可以使用

      添加项目
        item.Add(); 
      

      方法。并且它将支持诸如

      之类的方法
       if(item.Contains())
      

      如果这不是您真正想要的,请告诉我。抱歉,请注意,您的代码在发布时应该更好地格式化。我很难阅读它,不得不复制并粘贴到记事本并重新格式化。只是为了将来发布的注释。

      【讨论】:

      • ow..抱歉给您带来不便..在 item.Contains() 方法中我可以定义 item 字段 string_tag 吗?
      • @kate msdn.microsoft.com/en-us/library/bhkz42b3.aspx 解释了这种方法。吸和看是最好的学习方式。希望对你有帮助
      • 有一个 List 可以接受多个泛型参数吗?我只知道 List.
      • @Daniel..我相信通过建议包含你的意思是这样的 foreach (object_tag item in line_token) { if (item.string_tag.Contains("NP")) { Console.WriteLine(item .string_name); } } 但使用此方法不会比较列表项以查找它们之间的匹配项或检查项目是否是连续的..
      • msdn.microsoft.com/en-us/library/6sh2ey19.aspx 这个链接解释了所有方法,对不起,我无法提供更多帮助。
      猜你喜欢
      • 2020-04-15
      • 1970-01-01
      • 1970-01-01
      • 2019-01-28
      • 2021-08-23
      • 1970-01-01
      • 2011-05-30
      • 1970-01-01
      • 2021-05-30
      相关资源
      最近更新 更多