【问题标题】:.Net collection that maintains order and supports search for subset with matching order.Net 集合,维护顺序并支持搜索具有匹配顺序的子集
【发布时间】:2015-07-02 22:59:14
【问题描述】:

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

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

UPDATE 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();
}

【问题讨论】:

    标签: c# .net collections


    【解决方案1】:

    使用 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] ;
    

    【讨论】:

    • 感谢涂鸦。我认为 min 和 max 不起作用。我需要检查的实际超集集合将由整数(ID 值)组成,例如。 {1245、9485、2458}。更重要的是,SortedSet 似乎正如其名称所暗示的那样:添加 A、D、F、E 将创建一个集合 A、D、E、F
    • SortedSet.Min 和 SortedSet.Max 等价于 SortedSet[0] 和 SortedSet[SortedSet.Count-1]。如果要保持ADFE顺序,那么SortedSet就不合适了。
    【解决方案2】:

    好的,想通了。回顾一下用例:给定一个数组和一个较小数组的集合,创建一个数组集合,这些数组不是顺序很重要的较大数组的子集,即 { "A", "B", "C" } != { "C"、"B"、"A" } 和数组值在超集和子集数组中的连续索引中。

    我想有很多方法可以做到这一点,而我的方法可能不是性能最高的,但我正在使用的数组很小,所以这种方法可以完成工作。

    以下是控制台应用程序的完整代码:

    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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-18
      • 1970-01-01
      • 2011-04-11
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 2015-06-27
      相关资源
      最近更新 更多