0

现在的情况 :

HashSet<string> MasterSet => {100, 3}

HashSet <string> SubSet => {100, 3} or {100} or {100, 3, 1}

因此,从庞大的子集列表中,基于 MasterSet 我选择了这样的特定集:

if(MasterSet.SetEquals(subSet) || MasterSet.IsSupersetOf(subSet) || MasterSet.IsSubsetOf(subSet))

如果它为真,则使用该子集进行处理,否则循环其他可用集。

重复问题: 如果业务逻辑想要在主集和子集中包含重复,例如:

MasterSet => {100, 3, 3}

SubSet => {100, 3, 3} or {100, 3} or {100, 3, 3, 1}

那么 HashSet 的使用就被剥夺了。

如果我将 MasterSet 和 Subset 更改为List<string>

编辑: “BigYellowCactus”提供的解决方案有效。但是,如果我想使用标题而不是元素的顺序来匹配,过滤集合会更容易吗?

MasterSet => {100, 3, 4}
MasterHeaders => {"T","F","V"} //Headers element corresponds to the MasterSet element

情况1:

SubSet => {3, 100}
SubSetHeaders => {"F", "T"} //Headers element corresponds to the SubSet element

案例二:

SubSet => {4, 3}
SubSetHeaders => {"V", "F"} //Headers element corresponds to the SubSet element

是否可以先通过比较 MasterHeaders 和 SubSetHeaders 的标头进行匹配,然后按值进行匹配?

4

2 回答 2

1

您可以使用All扩展方法。

描述

确定序列的所有元素是否满足条件。


例子:

if (MasterSet.All(e => SubSet.Contains(e)) || SubSet.All(e => MasterSet.Contains(e)))
{
    //do stuff
}

选择:

if (!MasterSet.Except(SubSet).Any() || !SubSet.Except(MasterSet).Any())
{
    //do stuff
}

编辑:

正如Iridium 在他的评论中指出的那样,对于您不想匹配的情况,您可以通过简单地计算每个元素的出现SubSet { 100, 3, 3 } 进行。MasterSet = { 100, 100, 3 }

if (MasterSet.All(e => MasterSet.Count(r => r==e) <= SubSet.Count(r => r==e))
    || SubSet.All(e => SubSet.Count(r => r==e) <= MasterSet.Count(r => r==e)))
{
    //do stuff
}

(请注意,这可能不是最有效的方法......)


编辑2:

鉴于您基本上在序列中搜索序列,您可以使用以下方法:

void Main()
{
    var MasterSet = new List<string>() {"100", "3","4"};

    var SubSets = new[] 
    {
        new List<string>() {"100", "100", "3"},
        new List<string>() {"100", "3", "4"},
        new List<string>() {"32", "3423", "4234", "100", "3", "4", "34234"},
        new List<string>() {"100", "32", "3423", "4234", "100", "3", "4", "34234"},
        new List<string>() {"100", "32", "3", "4234", "100", "4", "34234"},
        new List<string>() {"100", "4", "3"},
        new List<string>() {"100", "3", "3"},
        new List<string>() {"100", "3"},
        new List<string>() {"100", "3", "3", "1"}
    };

    foreach (var SubSet in SubSets)
    {
        if (IsMatch(MasterSet, SubSet))
            Console.WriteLine(String.Join(", ", SubSet) + " is a \"subset\"");
        else if (IsMatch(SubSet, MasterSet))
            Console.WriteLine(String.Join(", ", SubSet) + " is a \"superset\"");
    }
}

bool IsMatch<T>(IEnumerable<T> source, IEnumerable<T> to_test)
{
    using (var enumerator = source.GetEnumerator())
    using (var sub_enumerator = to_test.GetEnumerator())
        while (sub_enumerator.MoveNext())
        {
            if (!enumerator.MoveNext())
                return false;
            if (!enumerator.Current.Equals(sub_enumerator.Current))
                sub_enumerator.Reset();
        }
    return true;
}

输出:

100, 3, 4 是“子集”
32, 3423, 4234, 100, 3, 4, 34234 是“超集”
100, 32, 3423, 4234, 100, 3, 4, 34234 是“超集”
100, 3 是一个“子集”

于 2012-07-25T10:57:58.500 回答
0

ISet<T>areHashSet<T>和的当前框架实现SortedSet<T>。这两个类都强制成员唯一性并且不允许重复。

虽然这可能首先看起来像是框架中的一个遗漏,但它实际上与数学集的属性和定义有关。正如这篇文章中所解释的,一个数学集没有重复的成员,逻辑{100, 3}上等价于{100, 3, 3}.

可能可以扩展List<T>实现ISet<T>,也许调用新类Sack<T>,但是,非唯一的实现ISet<T>将比框架中现有的实现更具挑战性,无需过多考虑,它似乎让人想起一般的背包问题

于 2012-07-25T11:02:54.753 回答