c# - 从结构数组中删除重复项

标签 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 bChecked;
}

我已将 stAppInfo 结构更改为类 here感谢 Jon Skeet

代码是这样的:(精简版)

stAppInfo[] appInfo = new stAppInfo[listView1.Items.Count];

int i = 0;
foreach (ListViewItem item in listView1.Items)
{
    appInfo[i].sTitle = item.Text;
    appInfo[i].sRelativePath = item.SubItems[1].Text;
    appInfo[i].sCmdLine = item.SubItems[2].Text;
    appInfo[i].bFindInstalled = (item.SubItems[3].Text.Equals("Sí")) ? true : false;
    appInfo[i].sFindTitle = item.SubItems[4].Text;
    appInfo[i].sFindVersion = item.SubItems[5].Text;
    appInfo[i].bChecked = (item.SubItems[6].Text.Equals("Sí")) ? true : false;
    i++;
}

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

编辑:

感谢大家的回答,但这个应用程序是“可移植的”,我的意思是我只需要 .exe 文件,我不想添加其他文件,如引用 *.dll,所以请不要使用此应用程序的外部引用在笔式驱动器中使用

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

ReadFile()
FillDataFromFileInAppInfoArray()
DeleteDuplicates()
FillListViewControl()

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

  1. 使用 ListView 数据
  2. 使用 appInfo 数组(这样更快??)
  3. 还有其他的吗?

编辑 2:

非常感谢:Jon Skeet 和 Michael Hays,感谢你们的宝贵时间!

最佳答案

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

其次,不要使用公共(public)字段。字段应该是一个实现细节 - 使用属性。

第三,我一点也不清楚这应该是一个结构。看起来比较大,而且不是特别“单值”。

第四,请关注.NET naming conventions因此您的代码适合用 .NET 编写的所有其他代码。

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

LINQ to Objects 可以让您使用 GroupBy 做到这一点如 Albin 所示,但(在我看来)更简洁的方法是使用 DistinctBy 来自 MoreLINQ :

var unique = appInfo.DistinctBy(x => new { x.sTitle, x.sRelativePath })
                    .ToArray();

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

我个人通常更喜欢使用 List<T>在数组上,但上面将为您创建一个数组。

请注意,使用此代码仍然可以有两个项目具有相同的标题,并且仍然可以有两个项目具有相同的相对路径 - 只是不能有两个项目具有相同的相对路径 标题。如果有重复项,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 });

这会给你一个 IEnumerable<appInfo>这是懒惰流式传输。请注意,如果您对其进行多次迭代,它迭代listView1.Items。相同的次数,每次执行相同的唯一性比较。

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

关于c# - 从结构数组中删除重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7059108/

相关文章:

.net - 使用 Azure 移动应用程序进行自定义身份验证

c#-4.0 - 具有动态内容的 XmlSerializer、XmlArray...怎么样?

c# - 在没有调试器的情况下运行测试时,Visual Studio 单元测试失败

c# - 如何实现带约束的泛型方法

c# - 在 Visual Studio 2017 中“找不到类型或命名空间”

c# - 如何测试lambda表达式的查询结果是否为null?

javascript - 1 到 150 之间由逗号和连字符分隔的有效字符串的正则表达式

c# - 如何在 C# 程序和 Node.js 程序之间使用 Msgpack?

.net - 错误 FS3039 : A direct reference to the generated type 'MyType' is not permitted

c# - 使用 MSTSCLib 进行远程桌面连接