Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从结构的数组中删除重复项_C#_.net_C# 4.0 - Fatal编程技术网

C# 从结构的数组中删除重复项

C# 从结构的数组中删除重复项,c#,.net,c#-4.0,C#,.net,C# 4.0,我无法从结构数组中删除重复项 我有这个结构: public struct stAppInfo { public string sTitle; public string sRelativePath; public string sCmdLine; public bool bFindInstalled; public string sFindTitle; public string sFindVersion; public bool bChe

我无法从结构数组中删除重复项

我有这个结构:

public struct stAppInfo
{
    public string sTitle;
    public string sRelativePath;
    public string sCmdLine;
    public bool bFindInstalled;
    public string sFindTitle;
    public string sFindVersion;
    public bool bChecked;
}
由于Jon Skeet

代码如下:(短版本)

我需要appInfo数组在sTitlesRelativePath成员中唯一,其他成员可以重复

编辑:

感谢所有人的回答,但这个应用程序是“可移植的”,我的意思是我只需要.exe文件,我不想添加其他文件,如references*.dll,所以请不要外部引用这个应用程序是打算在pendrive中使用

所有数据都来自一个*.ini文件,我所做的是:(伪代码)

当我想将数据保存到文件中时,我有以下选项:

  • 使用ListView数据
  • 使用appInfo阵列(这更快吗?)
  • 还有别的吗
  • EDIT2:


    非常感谢:乔恩·斯基特,迈克尔·海斯谢谢你们的时间伙计们

    使用LINQ2对象,按应唯一的对象分组,然后选择每组中的第一项

    var noDupes = appInfo.GroupBy(
        x => new { x.sTitle, x.sRelativePath })
        .Select(g => g.First()).ToArray();
    

    使用LINQ2对象,按应唯一的对象分组,然后选择每组中的第一项

    var noDupes = appInfo.GroupBy(
        x => new { x.sTitle, x.sRelativePath })
        .Select(g => g.First()).ToArray();
    
    首先,请不要使用可变结构。从各方面来说,它们都是个坏主意

    其次,请不要使用公共字段。字段应该是实现详细信息-使用属性

    第三,我根本不清楚这是否应该是一个结构。它看起来相当大,并不是特别的“单一值”

    第四,请遵循以下步骤,以便您的代码与.NET中编写的所有其他代码相匹配

    第五,不能从数组中删除项,因为数组是用固定大小创建的。。。但是您可以创建一个只包含唯一元素的新数组

    LINQ to Objects将允许您使用Albin所示的方法来实现这一点,但在我看来,更简洁的方法是从以下位置使用:

    这通常比GroupBy更高效,在我看来也更优雅

    就个人而言,我通常更喜欢使用
    List
    而不是数组,但上面的内容将为您创建一个数组

    注意,在这段代码中,仍然可以有两个项目具有相同的标题,并且仍然可以有两个项目具有相同的相对路径-只是不能有两个项目具有相同的相对路径和标题。如果存在重复项,
    DistinctBy
    将始终从输入序列中生成第一个此类项

    编辑:为了满足Michael的要求,您实际上不需要先创建数组,如果不需要,也不需要再创建数组:

    var query = listView1.Items
                         .Cast<ListViewItem>()
                         .Select(item => new stAppInfo
                                 {
                                     sTitle = item.Text,
                                     sRelativePath = item.SubItems[1].Text,
                                     bFindInstalled = item.SubItems[3].Text == "Sí",
                                     sFindTitle = item.SubItems[4].Text,
                                     sFindVersion = item.SubItems[5].Text,
                                     bChecked = item.SubItems[6].Text == "Sí"
                                 })
                         .DistinctBy(x => new { x.sTitle, x.sRelativePath });
    
    var query=listView1.Items
    .Cast()
    .选择(项目=>new stAppInfo
    {
    针=项目。文本,
    sRelativePath=item.SubItems[1]。文本,
    bfininstalled=item.SubItems[3]。Text==“Sí”,
    sFindTitle=item.SubItems[4]。文本,
    sFindVersion=item.SubItems[5]。文本,
    b检查=项。子项[6]。文本==“Sí”
    })
    .DistinctBy(x=>new{x.sTitle,x.sRelativePath});
    
    这将为您提供一个延迟流化的
    IEnumerable
    。请注意,如果您对它进行多次迭代,它将在
    listView1.Items
    上迭代相同的次数,每次执行相同的唯一性比较

    与Michael的方法相比,我更喜欢这种方法,因为它使“distinct by”列的语义非常清晰,并且消除了用于从
    ListViewItem
    中提取这些列的代码的重复。是的,它涉及到构建更多的对象,但我更喜欢清晰而不是效率,直到基准测试证明实际上需要更高效的代码

    首先,请不要使用可变结构。从各方面来说,它们都是个坏主意

    其次,请不要使用公共字段。字段应该是实现详细信息-使用属性

    第三,我根本不清楚这是否应该是一个结构。它看起来相当大,并不是特别的“单一值”

    第四,请遵循以下步骤,以便您的代码与.NET中编写的所有其他代码相匹配

    第五,不能从数组中删除项,因为数组是用固定大小创建的。。。但是您可以创建一个只包含唯一元素的新数组

    LINQ to Objects将允许您使用Albin所示的方法来实现这一点,但在我看来,更简洁的方法是从以下位置使用:

    这通常比GroupBy更高效,在我看来也更优雅

    就个人而言,我通常更喜欢使用
    List
    而不是数组,但上面的内容将为您创建一个数组

    注意,在这段代码中,仍然可以有两个项目具有相同的标题,并且仍然可以有两个项目具有相同的相对路径-只是不能有两个项目具有相同的相对路径和标题。如果存在重复项,
    DistinctBy
    将始终从输入序列中生成第一个此类项

    编辑:为了满足Michael的要求,您实际上不需要先创建数组,如果不需要,也不需要再创建数组:

    var query = listView1.Items
                         .Cast<ListViewItem>()
                         .Select(item => new stAppInfo
                                 {
                                     sTitle = item.Text,
                                     sRelativePath = item.SubItems[1].Text,
                                     bFindInstalled = item.SubItems[3].Text == "Sí",
                                     sFindTitle = item.SubItems[4].Text,
                                     sFindVersion = item.SubItems[5].Text,
                                     bChecked = item.SubItems[6].Text == "Sí"
                                 })
                         .DistinctBy(x => new { x.sTitle, x.sRelativePath });
    
    var query=listView1.Items
    .Cast()
    .选择(项目=>new stAppInfo
    {
    针=项目。文本,
    sRelativePath=item.SubItems[1]。文本,
    bfininstalled=item.SubItems[3]。Text==“Sí”,
    sFindTitle=item.SubItems[4]。文本,
    sFindVersion=item.SubItems[5]。文本,
    
    var query = listView1.Items
                         .Cast<ListViewItem>()
                         .Select(item => new stAppInfo
                                 {
                                     sTitle = item.Text,
                                     sRelativePath = item.SubItems[1].Text,
                                     bFindInstalled = item.SubItems[3].Text == "Sí",
                                     sFindTitle = item.SubItems[4].Text,
                                     sFindVersion = item.SubItems[5].Text,
                                     bChecked = item.SubItems[6].Text == "Sí"
                                 })
                         .DistinctBy(x => new { x.sTitle, x.sRelativePath });
    
    public class AppInfoComparer : IEqualityComparer<stAppInfo>
    {
        public bool Equals(stAppInfo x, stAppInfo y) {
            if (ReferenceEquals(x, y)) return true;
            if (x == null || y == null) return false;
            return Equals(x.sTitle, y.sTitle) && Equals(x.sRelativePath,
               y.sRelativePath);
        }
    
        // this part is a pain, but this one is already written 
        // specifically for your question.
        public int GetHashCode(stAppInfo obj) {
            unchecked {
                return ((obj.sTitle != null 
                    ? obj.sTitle.GetHashCode() : 0) * 397)
                    ^ (obj.sRelativePath != null 
                    ? obj.sRelativePath.GetHashCode() : 0);
            }
        }
    }
    
    var appInfoSet = new HashSet<stAppInfo>(new AppInfoComparer());
    foreach (ListViewItem item in listView1.Items)
    {
        var newItem = new stAppInfo { 
            sTitle = item.Text,
            sRelativePath = item.SubItems[1].Text,
            sCmdLine = item.SubItems[2].Text,
            bFindInstalled = (item.SubItems[3].Text.Equals("Sí")) ? true : false,
            sFindTitle = item.SubItems[4].Text,
            sFindVersion = item.SubItems[5].Text,
            bChecked = (item.SubItems[6].Text.Equals("Sí")) ? true : false};
        appInfoSet.Add(newItem);
    }
    
    stAppInfo[] appInfo = appInfoSet.ToArray();
    
    private class AppInfoComparer : IComparer<stAppInfo>
    {
       // return -1 if x < y, 1 if x > y, or 0 if they are equal
       public int Compare(stAppInfo x, stAppInfo y)
       {
          var comparison = x.sTitle.CompareTo(y.sTitle);
          if (comparison != 0) return comparison;
          return x.sRelativePath.CompareTo(y.sRelativePath);
       }
    }
    
    var appInfoSet = new SortedSet<stAppInfo>(new AppInfoComparer());