我不知道如何从结构数组中删除重复条目
我有这个结构:
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 数组在 sTitle 和 sRelativePath 成员中是唯一的,其他成员可以是重复的
编辑:
感谢大家的回答,但这个应用程序是“可移植的”,我的意思是我只需要 .exe 文件,我不想添加其他文件,如引用 *.dll,所以请不要使用此应用程序的外部引用在笔式驱动器中使用
所有数据都来自 *.ini 文件我所做的是:(伪代码)
ReadFile()
FillDataFromFileInAppInfoArray()
DeleteDuplicates()
FillListViewControl()
当我想将该数据保存到文件中时,我有以下选项:
- 使用 ListView 数据
- 使用 appInfo 数组(这样更快??)
- 还有其他的吗?
编辑 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/