[英]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 + b
与c + 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.