C# 使用组合键查询集合,其中关键部分可以匹配';任何';

C# 使用组合键查询集合,其中关键部分可以匹配';任何';,c#,collections,C#,Collections,是否有一个合适的集合或算法允许我使用复合键获取一个值,当查询键的某些部分时,该值可以为null,以表示匹配任何值 例如,如果我拥有该类: class Key { string p1{ get; } string p2{ get; } string p3{ get; } public Key(string p1, string p2 , string p3) { this.p1 = p1; this

是否有一个合适的集合或算法允许我使用复合键获取一个值,当查询键的某些部分时,该值可以为null,以表示匹配任何值

例如,如果我拥有该类:

    class Key
    {
        string p1{ get; }
        string p2{ get; }
        string p3{ get; }

        public Key(string p1, string p2 , string p3)
        { this.p1 = p1;  this.p2 = p2; this.p3=p3;  }
    }
如果我创建了三个关键点,例如

new Key( "a","b","c")
new Key( "d","b","c")
new Key( "e","f","c")
我想要一个不进行迭代的集合或算法,以允许使用以下键

new Key( null, "b","c") to return the values mapped to the first two keys,
new key( null,null,"c") to return the values mapped to all of the keys.

有什么方法可以做到这一点吗?

对于通过三个关键组件的任意组合进行查找,可能都可以做到这一点。请注意,为了简单起见,配对查找的密钥(A+B)由simple concat创建。真正的键应该是Tuple

var keys = new[] { new Key("a", "b", c"), ... };

class Map
{
  // ... skip members declaration here
  public Map(IEnumerable<Keys> keys)
  {
    all = keys;

    mapA = keys.ToLookup(k => k.A);
    mapB = keys.ToLookup(k => k.B);
    mapC = keys.ToLookup(k => k.C);

    // should be keys.ToLookup(k => Tuple.Create(k.A, k.B))
    mapAB = keys.ToLookup(k => k.A + k.B);
    mapAC = keys.ToLookup(k => k.A + k.C);
    mapBC = keys.ToLookup(k => k.B + k.C);

    mapABC = keys.ToLookup(k => k.A + k.B + k.C);
  }

  public IEnumerable<Key> Find(Key k)
  {
    if(k.A == null && k.B == null && k.C == null) return all;

    if(k.A != null && k.B == null && k.C == null) return mapA[k.A];
    if(k.A == null && k.B != null && k.C == null) return mapB[k.B];
    if(k.A == null && k.B == null && k.C != null) return mapC[k.C];

    if(k.A != null && k.B != null && k.C == null) return mapAB[k.A+k.B];
    if(k.A != null && k.B == null && k.C != null) return mapAC[k.A+k.C];
    if(k.A == null && k.B != null && k.C != null) return mapBC[k.B+k.C];

    return mapABC[k.A+k.B+k.C];
  }
}
var Key=new[]{new Key(“a”、“b”、“c”),…};
类图
{
//…跳过此处的成员声明
公共地图(IEnumerable键)
{
全部=钥匙;
mapA=keys.ToLookup(k=>k.A);
mapB=keys.ToLookup(k=>k.B);
mapC=keys.ToLookup(k=>k.C);
//应该是keys.ToLookup(k=>Tuple.Create(k.A,k.B))
mapAB=keys.ToLookup(k=>k.A+k.B);
mapAC=keys.ToLookup(k=>k.A+k.C);
mapBC=keys.ToLookup(k=>k.B+k.C);
mapABC=keys.ToLookup(k=>k.A+k.B+k.C);
}
公共IEnumerable查找(键k)
{
如果(k.A==null&&k.B==null&&k.C==null)返回全部;
如果(k.A!=null&&k.B==null&&k.C==null)返回mapA[k.A];
if(k.A==null&&k.B!=null&&k.C==null)返回mapB[k.B];
如果(k.A==null&&k.B==null&&k.C!=null)返回mapC[k.C];
如果(k.A!=null&&k.B!=null&&k.C==null)返回mapAB[k.A+k.B];
如果(k.A!=null&&k.B==null&&k.C!=null)返回mapAC[k.A+k.C];
如果(k.A==null&&k.B!=null&&k.C!=null)返回mapBC[k.B+k.C];
返回mapABC[k.A+k.B+k.C];
}
}

我想您可以创建3个单独的字典,每个字典都包含一个键部分。编辑:这意味着您每次最多可以进行3次查找,如果您想按2个值进行查找,则3个字典是不够的。您需要为第一个、第二个和第三个键创建3个字典。然后为每个-(1,2)对(2,3)创建1个字典pair和(1,3)pair。基本上是一个问题,即是否有一种结构允许通过掩码进行查找比完全O(N)更快列表扫描。还有那段代码,它是编译的还是自动属性缺少编译器警告/错误
setter
?很抱歉,这是我手机上手工写的,所以无法检查编译警告或错误。Alexander很好地总结了这个问题。还假设在关键类中有10或20个字段,dict的数量onaries可能会失控。