.Net集合,维护订单并支持搜索具有匹配顺序的子集

时间:2015-07-02 22:59:14

标签: c# .net collections

是否有.Net集合维护订单并支持搜索匹配顺序的子集。

更新1 :我开发了一种适用于我的方法,并在下面回答了我自己的问题。但是,在我看到是否有人提出更好的方法之前,我不会将其标记为答案。

更新2 :等了几天;交通不多,没有建议,所以我继续前进 并将我的答案标记为我实施的答案。

用例:我有一个特定顺序的对象集合(例如字符串或整数),我需要确定另一个集合是否是超集的确切子集,即顺序问题,ABC与CBA不同

首先请注意我只使用SortedSet来说明我想要完成的内容。它没有做我需要做的事情。所以你可以把它想象成伪代码:

static void Main(string[] args)
{
    var fleet = new List<string>();
    fleet.Add("MotherShip");

    var motherShip = new SortedSet<string>();
    var motherArray = new string[7] { "A", "B", "C", "D", "E", "F", "G" };
    for (int i = 0; i < motherArray.Length; i++)
    {
        motherShip.Add(motherArray[i]);
    }

    var shipOne = new SortedSet<string>();
    var shipOneArray = new string[6] { "A", "B", "C", "D", "E", "F" };
    for (int i = 0; i < shipOneArray.Length; i++)
    {
        shipOne.Add(shipOneArray[i]);
    }
    // shipOne should NOT be added
    if (!shipOne.IsProperSubsetOf(motherShip)) fleet.Add("ShipOne");

    var shipTwo = new SortedSet<string>();
    var shipTwoArray = new string[6] { "B", "C", "D", "E", "F", "G" };
    for (int i = 0; i < shipTwoArray.Length; i++)
    {
        shipTwo.Add(shipTwoArray[i]);
    }
    // shipTwo should NOT be added
    if (!shipTwo.IsProperSubsetOf(motherShip)) fleet.Add("ShipTwo");

    var shipThree = new SortedSet<string>();
    var shipThreeArray = new string[5] { "E", "B", "C", "D", "A" };
    for (int i = 0; i < shipThreeArray.Length; i++)
    {
        shipThree.Add(shipThreeArray[i]);
    }
    // shipThree SHOULD BE added
    if (!shipThree.IsProperSubsetOf(motherShip)) fleet.Add("ShipThree");

    Console.WriteLine("Fleet has {0} ships. Press any key to continue.", fleet.Count);
    // Need it to be: Fleet has 2 ships.

    Console.ReadLine();
}

2 个答案:

答案 0 :(得分:0)

使用SortedSet并不是一个坏主意。

SortedSet SearchedArray = new Sorted { ... } // What you are looking for
SortedSet ExtractArray = MotherArray.GetViewBetween(SearchedArray.Min,SearchedArray.Max) ;
bool found=ExtractArray.Count==SearchedArray.Count;
for (int i=0;i<SearchedArray.count && found; i++) found=ExtractArray[i]==SearchedArray[i] ;

答案 1 :(得分:0)

好的,明白了。回顾一下用例:给定一个数组和一个较小数组的集合,创建一个数组集合,这些数组不是顺序重要的较大数组的子集,即{&#34; A&#34;,&#34; B&# 34;,&#34; C&#34; }!= {&#34; C&#34;,&#34; B&#34;,&#34; A&#34;并且数组值在超集和子集数组中都是连续的索引。

我想有很多方法可以实现这一点,我的方法可能不是最高效的,但我使用的阵列很小,所以这种方法可以完成工作。

这里是控制台应用程序的完整代码:

private static void Main(string[] args)
{
    // This is the master list of IDs - no repeats. Hard coded here for the example.
    var masterDictionary = new Dictionary<string, int>();
    var masterArray = new string[15] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "K", "L", "M", "N", "O", "P" };
    for (var i = 0; i < masterArray.Length; i++)
    {
        masterDictionary.Add(masterArray[i], i);
    }

    var uniqueArrays = GetUniqueArrays(masterDictionary);

    Console.WriteLine("Unique array collection has {0} arrays. Press any key to continue.", 
        uniqueArrays.Count);
    Console.ReadLine();
}

/// <summary>
/// Create a collection of arrays which are not subsets of a larger array where order matters,
/// i.e. { "A", "B", "C" } != { "C", "B", "A" } and the array values are in contiguous 
/// indexes in both the superset and subset arrays.
/// </summary>
/// <returns></returns>
private static List<string[]> GetUniqueArrays(Dictionary<string, int> masterDictionary)
{
    // This is the list of subsets I'll return
    var uniqueArrays = new List<string[]>();

    // This the superset of IDs, no repeats. We'll use an ordered dictionary because
    // we need to find values in it by index.
    var supersetDictionary = new OrderedDictionary();
    var supersetArray = new string[7] { "A", "B", "C", "D", "E", "F", "G" };
    for (var i = 0; i < supersetArray.Length; i++)
    {
        var value = 0;
        masterDictionary.TryGetValue(supersetArray[i], out value);
        supersetDictionary.Add(supersetArray[i], value);
    }

    // The superset array will always be in the list we return.
    uniqueArrays.Add(supersetArray);

    // Hard code some subsets and add them to a collection
    var subsets = new List<string[]>();

    // Is a subset
    var subsetOne = new string[6] { "A", "B", "C", "D", "E", "F" };
    subsets.Add(subsetOne);

    // Is a subset
    var subsetTwo = new string[6] { "B", "C", "D", "E", "F", "G" };
    subsets.Add(subsetTwo);

    // Is a subset
    var subsetThree = new string[3] { "B", "C", "D" };
    subsets.Add(subsetThree);

    // Is NOT a subset
    var subsetFour = new string[3] { "D", "C", "B" };
    subsets.Add(subsetFour);

    // Check if the subsetArray is a subset of the supersetArray. If it is not
    // then add it to the list of unique subsets
    foreach (var subset in subsets)
    {
        if (!CheckIsSubset(masterDictionary, supersetDictionary, subset)) 
            uniqueArrays.Add(subset);
    }

    return uniqueArrays;
}

/// <summary>
/// Determine an array is a subset of a larger array where order matters,
/// i.e. { "A", "B", "C" } != { "C", "B", "A" } and the array values are in 
/// contiguous indexes in both the superset and subset arrays.
/// </summary>
/// <param name="masterSet"></param>
/// <param name="superset"></param>
/// <param name="subset"></param>
/// <returns></returns>
private static bool CheckIsSubset(Dictionary<string, int> masterSet, 
    OrderedDictionary superset, string[] subset)
{
    var supersetIndex = -1;
    for (var i = 0; i < subset.Length - 1; i++)
    {
        // Get the masterDictionary value for the first ID in the subsetArray
        var idValue = -1;
        masterSet.TryGetValue(subset[i], out idValue);
        if (idValue >= 0)
        {
            // Next determine if the first ID in the subset array is in the superset.
            if (supersetIndex == -1)
            {
                for (var j = 0; j < superset.Count; j++)
                {
                    // Get the ID at index j from the superset and compare it to subset ID
                    var supersetId = superset.Cast<DictionaryEntry>().ElementAt(j).Key.ToString();
                    var subsetId = subset[i];
                    if (subsetId == supersetId)
                    {
                        // This is the index in the superset from where we want to start our comparison
                        supersetIndex = j;
                        break;
                    }
                }

                // The first ID is not in the superset so we know the array we're testing is not
                // a subset.
                if (supersetIndex == -1)
                {
                    return false;
                }
            }
        }
        else
        {
            var error = string.Format("The ID {0} is not in the master list.", idValue);
            throw new Exception(error);
        }

        // We have a match. Next we want to step through the subset array.
        // We next test for matches in the adjoining indexes
        supersetIndex++;
        if (superset.Count >= supersetIndex)
        {
            // Get the superset value at this index and compare it to the subset value
            var supersetKey = superset.Cast<DictionaryEntry>().ElementAt(supersetIndex).Key.ToString();
            var subsetValue = subset[i + 1];
            if (subsetValue != supersetKey) return false;
        }
        else
        {
            // The supersetIndex is at or greater than the length of the superset array
            // so our subset is unique.
            return false;                    
        }
    }

    // The array we're examining is a subset of the larger array
    return true;
}