c# - 使用 C# 中的字典,将某些自定义类属性用作同一类中另一个属性(形成为值)的唯一键

标签 c# linq dictionary data-structures

我有一个类类型,如下所示的 ValueSetting,我正在尝试迭代 List< ValueSetting >,这样对于列表中 param1、param2、param3 的所有常见条目,我必须对每个 param4 执行特定操作。让我解释 。在下表中,带有红色箭头标记的条目(param1、param2、param3)应该类似于 param4(500, 600) 的 list 的键。因此整合它们

10, foo, abc => (500, 600)

20、嘘、abc =>( 500, 600)

30、foo、abc => (500)

那么,这是我可以将 param1、param2、param3 作为 List< param4 value> 的键放入字典中的东西吗?这是怎么做到的?还是有更好的方法来存储它们而不是字典?

enter image description here

public class ValueSetting 
{  
  public int param1;
  public string param2;
  public string param3;
  public int param4;
}

最佳答案

按照您询问 LINQ ToLookup method 的方式构建数据可以使用。来自 MSDN:

The ToLookup method returns a Lookup, a one-to-many dictionary that maps keys to collections of values. A Lookup differs from a Dictionary, which performs a one-to-one mapping of keys to single values.

要使用 ToLookup 方法创建 Lookup,我们应该定义:

  • key 类,重写了 GetHashCodeEquals 方法;这个key类将定义如何对输入数据进行分组;
  • keySelector 将用于根据输入数据创建键;
  • elementSelector 将用于选择适当键的值。

第一种方法:使用匿名类型作为 key 。

我们可以使用anonymous type作为创建 Lookup 的键。 匿名类型自动实现GetHashCodeEquals。来自 MSDN:

Because the Equals and GetHashCode methods on anonymous types are defined in terms of the Equals and GetHashCode methods of the properties, two instances of the same anonymous type are equal only if all their properties are equal.

以下是我们如何使用匿名类型作为键创建Lookup:

var list = new List<ValueSetting>
{
    new ValueSetting {param1 = 10, param2 = "foo", param3 = "abc", param4 = 500},
    new ValueSetting {param1 = 20, param2 = "boo", param3 = "abc", param4 = 500},
    new ValueSetting {param1 = 10, param2 = "foo", param3 = "abc", param4 = 600},
    new ValueSetting {param1 = 20, param2 = "boo", param3 = "abc", param4 = 600},
    new ValueSetting {param1 = 30, param2 = "foo", param3 = "abc", param4 = 500},
};

var lookup = list.ToLookup(
    vs => new {vs.param1, vs.param2, vs.param3}, // Group key.
    vs => vs.param4);                            // Group values.

foreach (var item in lookup)
{
    Console.WriteLine("{0} => ({1})", item.Key, string.Join(", ", item.Select(i => i)));
}

如果您要在单个方法中使用Lookup,则此方法很方便,因为匿名类型的对象无法从该方法返回并作为参数传递给另一个方法。


第二种方法:引入关键类。

另一种方法是定义一个将用作分组键的类。在这个类中我们应该重写 GetHashCodeEquals方法。如果您使用 Visual Studio 2015 或更高版本,那么您可以 automatically generate these members 。以下是我们如何定义此类:

public class Key
{
    public int param1;
    public string param2;
    public string param3;

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != GetType()) return false;
        Key other = (Key) obj;
        Key other = (Key) obj;
        return param1 == other.param1 && 
               string.Equals(param2, other.param2) && 
               string.Equals(param3, other.param3);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            var hashCode = param1;
            hashCode = (hashCode * 397) ^ (param2 != null ? param2.GetHashCode() : 0);
            hashCode = (hashCode * 397) ^ (param3 != null ? param3.GetHashCode() : 0);
            return hashCode;
        }
    }
}

然后使用这个关键类,我们可以创建一个Lookup:

var list = new List<ValueSetting>
{
    new ValueSetting {param1 = 10, param2 = "foo", param3 = "abc", param4 = 500},
    new ValueSetting {param1 = 20, param2 = "boo", param3 = "abc", param4 = 500},
    new ValueSetting {param1 = 10, param2 = "foo", param3 = "abc", param4 = 600},
    new ValueSetting {param1 = 20, param2 = "boo", param3 = "abc", param4 = 600},
    new ValueSetting {param1 = 30, param2 = "foo", param3 = "abc", param4 = 500},
};

ILookup<Key, int> lookup = list.ToLookup(
    vs => new Key {param1 = vs.param1, param2 = vs.param2, param3 = vs.param3}, // Group key.
    vs => vs.param4); // Group values.

foreach (IGrouping<Key, int> item in lookup)
{
    Console.WriteLine("{0}, {1}, {2} => ({3})",
        item.Key.param1, item.Key.param2, item.Key.param3,
        string.Join(", ", item.Select(i => i)));
}

如果您想从方法返回Lookup,或者将其作为参数传递给另一个方法,或者存储为类的属性(以及在创建时的其他情况下),则可以使用此方法Lookup 必须在创建它的方法之外使用)。

关于c# - 使用 C# 中的字典,将某些自定义类属性用作同一类中另一个属性(形成为值)的唯一键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61377959/

相关文章:

c# - HttpClient 下载文件 OutOfMemory 错误

c# - Swift 中的 init 与 C# 中的构造函数相同吗?

c# - 根据用户角色在运行时创建菜单

python - 在python中对多级字典进行排序

Python 2.7.8 : Printing a sub-dictionary value?

c# - 使用菜单项而不是导航 url 添加按钮单击事件

c# - 单元测试异常处理

c# - 如何在 C# 中过滤包含另一个列表的列表?

c# - 如何将此 SQL 查询转换为 EF Core 中的 LINQ 查询?

java - 从 TreeMap 获取 Integer 并分配给 int 时出现 NullPointerException