【问题标题】:How to find whether entry exists or not in the List<struct> in C#?如何在 C# 中的 List<struct> 中查找条目是否存在?
【发布时间】:2017-08-07 11:40:01
【问题描述】:

我有文本框,我获取并将其输入设置为如下结构。

public struct mappingData
{
    public string a;
    public string b;
    public int c;
}
mappingData mappingFileData;
public List<mappingData> mappingDatabase = new List<mappingData>();`

单击按钮后,我将其存储到列表中

private void btnAddMapData_Click(object sender, EventArgs e)
{
mappingFileData.a = addressPrefixMbDataType[cbMbDataType.SelectedIndex];
mappingFileData.b = addressPrefixMbValue[cbMbValue.SelectedIndex];
mappingFileData.c = Int32.Parse(tbAddress.Text);

// Add new entry to the linked list each time when 'btnAddMapData' is clicked 
mappingDatabase.Add(mappingFileData);
}

现在可以关注我的数据库了

a , x , 1

a , x , 2

b , x , 1

b , x , 2

但不应该是这样的

a , x , 1

a , x , 1> > 重复因为“1”之前已经可用

b , x , 2

b , x , 2 > 重复因为“2”之前已经可用

b , x , 1> > 不是重复的,因为第一个参数不同,即 'b' 所以“a”和“b”都可以保持 1,因为两者不同,但如果有列表中有两个“a”,那么应该只有一个“1”。

请给我一个建议

【问题讨论】:

  • 两个项目被视为相等(重复)的确切规则是什么? IE。你能否提供一个方法public bool Equals(mappingData a, mappingData b) 的实现,如果ab 是重复的,则返回true,否则false
  • 我建议您将结构更改为类。然后你可以实现 IEquatable> 接口。之后你应该可以使用 mappingDatabase.Contains()

标签: c# winforms


【解决方案1】:

如果您想要一种可靠的方法来检查重复项,您必须首先修改您的结构以覆盖 == 运算符和相关方法:

public struct mappingData
{
    public string mbDataType;
    public string mbValue;
    public string daliAddrType;
    public int mbAddress;
    public string daliCmdNo;
    public int daliDevId;

    public override bool Equals(Object obj)
    {
        return obj is mappingData && this == (mappingData)obj;
    }

    public override int GetHashCode()
    {
        return (mbDataType.GetHashCode() + mbValue.GetHashCode() + daliAddrType.GetHashCode() + daliCmdNo.GetHashCode()) * mbAddress * 807403 * daliDevId;
    }

    public static bool operator ==(mappingData x, mappingData y)
    {
        return x.mbDataType == y.mbDataType && x.mbValue == y.mbValue && x.daliAddrType == y.daliAddrType && x.mbAddress == y.mbAddress && x.daliCmdNo == y.daliCmdNo && x.daliDevId == y.daliDevId;
    }

    public static bool operator !=(mappingData x, mappingData y)
    {
        return !(x == y);
    }
}

现在,您可以使用 LINQ 或类似方法并比较 mappingData 的相同实例:

if (!mappingDatabase.Contains(mappingFileData))
{
    mappingDatabase.Add(mappingFileData);
}

编辑:

如果您想要检查相同的mbAddressmbDataType,那么您根本不需要修改您的结构。您可以立即执行此操作:

if (!mappingDatabase.Any(m => m.mbAddress == mappingFileData.mbAddress && m.mbDataType == mappingFileData.mbDataType))
{
    mappingDatabase.Add(mappingFileData);
}

【讨论】:

  • 我很困惑,请更新此结构的代码 public struct mappingData { public string mbDataType;公共字符串mbValue;公共字符串 daliAddrType;公共 int mbAddress;公共字符串 daliCmdNo;公共 Int32 daliDevId; }
  • 使用 XOR 进行哈希码计算可能会导致更多的冲突,这可能超出预期。最好使用素数执行未经检查的乘法:stackoverflow.com/questions/38280843/…
  • @kaviarasan 查看编辑。其实很简单。您在GetHashCode() 方法中使用每个字段的哈希码,并将x 的所有字段与== 覆盖中y 的所有字段进行比较。
  • 我不知道你是否回答我的问题,因为我从未使用过哈希码,所以这让我很困惑。我会在这里再次为你解释我的问题。
  • @kaviarasan 您的问题是如何检查重复项。答案是将这些方法添加到您的结构中,然后您可以使用Contains
【解决方案2】:

如果您使用struct,默认实现会考虑所有字段以生成生成的哈希码。因此,只需将您的结构放入 HashSet&lt;&gt; 即可解决您的问题:

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

public class Program
{
    public static void Main()
    {
        var items = Enumerable.Range(1, 100)
                              .Select(value => value % 10)
                              .Select(value => new mappingData{ a = "a" + value, b = "b" + value, c = value });
        var hashSet = new HashSet<mappingData>(items);

        // Outputs only first ten elements
        foreach(var item in hashSet)
        {
            Console.WriteLine(item);
        }

    }

    public struct mappingData
    {
        public string a;
        public string b;
        public int c;

        public override string ToString()
        {
            return $"{a} {b} {c}";
        }
    }
}

【讨论】:

    【解决方案3】:

    List 有几种扩展方法可以帮助您在列表中查找数据。在您的情况下,我建议使用 Count 方法。它也应该适用于结构。

    int found = mappingDatabase.Count(delegate (mappingData obj) { return obj.a.Equals("a") && obj.b.Equals("x"); });
    

    然后您可以设置自己的搜索规则并确定它是否重复。

    在调用 Count 之前不要忘记检查 mappingDatabase 是否为空。

    【讨论】:

    • @Corak,mappingDatabase 是一个列表,所以它可以为空
    • 我不想在公共 int c 中重复;?
    • 如果找到 > 0 则该项目已经存在,因此您不要添加它。或者您可以使用 Find 并返回列表中已经存在的项目(否则它将为空)
    猜你喜欢
    • 2020-12-12
    • 1970-01-01
    • 2012-02-14
    • 1970-01-01
    • 1970-01-01
    • 2021-01-10
    • 1970-01-01
    相关资源
    最近更新 更多