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))

true の場合はその 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

ケース 2:

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
}

編集:

イリジウムがコメントで指摘したように一致させたく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>HashSet<T>SortedSet<T>です。これらのクラスはどちらもメンバーの一意性を強制し、重複を許可しません。

これは最初はフレームワークの省略のように見えるかもしれませんが、実際には数学的集合のプロパティと定義に関連しています。この投稿で説明されているように、数学的集合には重複するメンバーがなく、論理的{100, 3}には{100, 3, 3}.

おそらく新しいクラスを呼び出して、List<T>implementに拡張することは可能かもしれませんが、 の非固有の実装は、フレームワークに存在するものよりもはるかに困難であり、あまり考えずに、一般的なナップサックの問題を思い起こさせるようです。ISet<T>Sack<T>ISet<T>

于 2012-07-25T11:02:54.753 に答える