簡體   English   中英

可比較的數據設計模式合並

[英]Comparable merge of data design pattern

在以下場景中是否存在比較數據的模式或最佳實踐:

每個字母代表一大塊數據,在我的例子中是XML。

a+b+c+d

這些合並為一個並返回。 如果我事先已經合並了一個+ b + c,那么識別這個“包”然后添加d將非常簡單。 但如果我緩存了怎么辦?

a+c+d

然后對a + b + c + d的請求來了,通過所有這些可能的組合以確定將b添加到a + c + d包中的最佳方法是什么?

合並數據的順序並不重要。 雖然它可能對答案沒有任何影響,但代碼是用C#4.0編寫的。

再編輯一個例子:

可能的元素: a,b,c,d,e,f

假設我收到了一個請求: a + c + d + e意味着一個數組,其中0=a,1=c,2=d,3=e

在我的“緩存”中,我有以下內容: c + d + e已經合並

然后根據要求,我必須找到一種方法來做類似的事情:

if(cache.Contains(request.elements[0]+request.elements[1] etc...))
else(cache.Contains(request.elements[1] + request.elements[2] etc...))

它可能需要某種遞歸for循環,但由於我的情況下可能的元素最終在2-5000范圍內,因此它需要盡可能快速有效。

根據這個:

“然后對a + b + c + d的請求出現了,通過所有這些可能的組合以確定將a添加到a + c + d包中會得到所需結果的最佳方法是什么?”

我假設訂單無關緊要,因此如果你想要“abcd”,可以將“b”與“acd”合並。 唯一重要的是包含哪些元素。

現在,我不知道你使用什么XML或者你如何合並它,所以我用合並字符串編寫了這個,並通過簡單地連接它們來合並。 您將不得不重寫Merge方法來執行您想要執行的任何操作(並將string更改為您正在使用的任何內容)。 我也使用整數而不是a,b,c因為我假設你會比字母表中的字母更多。

此外,例如,當您正在尋找a + b + c + d + e + f + g ,並且緩存中的最佳匹配是c + e + g + f ,那么它也會在緩存中查找最佳匹配余數, a + b + d ,依此類推,以進一步減少合並次數。 如果您不想要這個(如果使用您的xml,則無法將a + bc + d合並a + b + c + d ),您可以輕松地重寫它,但是它會平均進行更多合並。

這應該非常快。 查看main函數中的注釋,了解它的作用。

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication17
{
    class CachedMerger
    {
        private Dictionary<HashSet<int>, string> _cache = new Dictionary<HashSet<int>, string>();
        private Dictionary<int, string> _items = new Dictionary<int, string>();

        public void AddItem(int index, string item)
        {
            _items[index] = item;
        }

        public void RemoveItem(int index)
        {
            _items.Remove(index);
        }

        private string Merge(string a, string b)
        {
            return a + b;
        }

        private string Merge(HashSet<int> list)
        {
            var sb = new StringBuilder();
            foreach (var index in list)
            {
                if (!_items.ContainsKey(index))
                    return null;
                else
                    sb.Append(_items[index]);
            }

            return sb.ToString();         
        }

        public string Get(HashSet<int> query)
        {
            var bestMatchKey = BestMatchKey(query);
            if (bestMatchKey == null)
            {
                var result = Merge(query);

                if (result == null)
                    throw new Exception("Requested item not found in the item list.");

                _cache[query] = result;
                return result;
            }
            else
            {
                if (bestMatchKey.Count == query.Count)
                    return _cache[bestMatchKey];

                var missing = new HashSet<int>();
                foreach (var index in query)
                    if (!bestMatchKey.Contains(index))
                        missing.Add(index);

                return Merge(_cache[bestMatchKey], Get(missing));
            }
        }

        private HashSet<int> BestMatchKey(HashSet<int> set)
        {
            int bestCount = 0;
            HashSet<int> bestKey = null;
            foreach (var entry in _cache)
            {
                var key = entry.Key;
                int count = 0;
                bool fail = false;
                foreach (var i in key)
                {
                    if (set.Contains(i))
                    {
                        count++;
                    }
                    else
                    {
                        fail = true;
                        break;
                    }
                }

                if (!fail && count > bestCount)
                {
                    bestKey = key;
                    bestCount = count;
                }
            }
            return bestKey;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var cm = new CachedMerger();
            // Add all the base parts
            cm.AddItem(0, "sjkdlajkld");
            cm.AddItem(1, "dffdfdfdf");
            cm.AddItem(2, "qwqwqw");
            cm.AddItem(3, "yuyuyuyy");
            cm.AddItem(4, "kjkjkjkjkj");
            cm.AddItem(5, "oioyuyiyui");

            // This will merge 0 + 1 + 3 + 4 since the cache is empty
            Console.WriteLine(cm.Get(new HashSet<int> { 0, 1, 3, 4 }));
            // This will merge 2 + 5 as there is no match in the cache
            Console.WriteLine(cm.Get(new HashSet<int> { 2, 5 }));
            // This will merge (2 + 5) from the cache with 3
            Console.WriteLine(cm.Get(new HashSet<int> { 2, 3, 5 }));
            // This will merge (0 + 1 + 3 + 4) from the cache with (2 + 5) from the cache
            Console.WriteLine(cm.Get(new HashSet<int> { 0, 1, 2, 3, 4, 5 }));

            Console.Read();
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM