【问题标题】:Splitting contents of a dictionary based on size根据大小拆分字典的内容
【发布时间】:2018-06-26 20:39:21
【问题描述】:

问题定义

我有一本<string, Tuple<List<T>, int>> 形式的字典。元组的 Item2 是 Item1 (List) 的字节大小。

我想根据每个字典的预定义最大大小将其分成多个字典,每个字典形式为 <string, List<T>>

因此,我可能不得不分解一个值列表(List<T>;元组的第 1 项)(对应于单个 K-V 对)以进入多个字典。

到目前为止我已经尝试过什么

我想出了下面的代码,它以一种非常原始的方式进行分块 - 这仍然是 WIP,还没有完全工作。这里的逻辑是遍历每个 K-V 对并从列表中获取所有项目,直到我们达到预先定义的上述最大大小。

但在我进一步处理这段代码之前,我觉得必须有更好的方法来做到这一点。任何指针表示赞赏。

private async Task ChunkAsPerPayloadSizeAsync(IDictionary<string, Tuple<List<T>, int>> bufferSnapshot)
{
    var dict = GetDictionary(bufferSnapshot); // This return the bufferSnapshot dictionary in the form <string, List<T>>
    if (GetSizeOfDictionaryInBytes(dict) <= PayloadSizeInBytes)
    {
        await _makeRequest(dict); // This is a callback with the chunk in the correct size
    }
    else
    {
        var dict2 = new Dictionary<string, List<T>>();
        var sizeInBytes = 0;
        while (bufferSnapshot.Count > 0)
        {
            var itemId = bufferSnapshot.FirstOrDefault().Key;
            if (bufferSnapshot.TryGetValue(itemId, out var data))
            {
                var thisSize = data.Item2 + FindSize<string>.SizeOf(itemId);
                if (sizeInBytes + thisSize <= PayloadSizeInBytes)
                {
                    sizeInBytes += thisSize;
                    dict2.Add(itemId, data.Item1);
                    bufferSnapshot.Remove(itemId);
                }
                else
                {
                    // now we have to chunk the values
                    var sizeInBytesOfValuesList = data.Item2;
                    var valuesCount = data.Item1.Count;
                    var sizePerValue = sizeInBytesOfValuesList / valuesCount;
                    var spaceAvailable = RequestPayloadSizeInBytes - sizeInBytes - FindSize<string>.SizeOf(itemId);
                    var numberOfValuesToTake = spaceAvailable / sizePerValue;
                    if (numberOfValuesToTake > 0)
                    {
                        if (numberOfValuesToTake < data.Item1.Count)
                        {
                            var items = data.Item1.Take(numberOfValuesToTake);
                            data.Item1.RemoveRange(0, numberOfValuesToTake);
                            dict2.Add(itemId, items.ToList());
                        }
                        else
                        {
                            dict2.Add(itemId, data.Item1);
                        }
                    }
                }
            }
        }
    }
}

【问题讨论】:

  • 如果你已经有了大小,你可以使用Where根据元组报告的大小过滤字典,然后使用Except得到其余的,然后在结果上简单地调用ToDictionary .我不知道你在所有这些代码中究竟在做什么什么,因为我不敢直视它,以免我掉进兔子洞。
  • 我不太清楚。你想要一份清单吗?每个元组都有一个最大大小的元素?您应该提供更多信息
  • 这是knapsack-type problem,您是在尝试将尽可能多的项目塞入每个存储桶中,还是可以只遍历项目直到找到一个超过 maxSize 的项目,然后从下一个桶开始?
  • @itsme86,是的,这是一个背包式问题。更像是 2 个嵌套的背包问题。
  • 为什么投反对票?我有一个问题陈述,我自己努力的代码示例,并且明确指出我正在寻找指针,而不是勺子喂养的解决方案。上面评论中指向背包问题的指针实际上有所帮助。

标签: c# .net dictionary chunking


【解决方案1】:

您能否bufferSnapshot.Select(b =&gt; b.Item2) 给您一个长度数组,然后使用 Take/Skip 将您想要的元素抓取到您所追求的较短序列中?

【讨论】:

  • 那行不通,因为我还需要分解值列表(元组的第 1 项)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
  • 2015-03-24
  • 2015-07-23
相关资源
最近更新 更多