根据大小拆分字典的内容

时间:2018-01-17 21:09:38

标签: c# .net dictionary chunking

问题定义

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

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

因此,我可能需要分解值列表(List<T>;元组的Item1)(对应于单个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);
                        }
                    }
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

你可以bufferSnapshot.Select(b => b.Item2)给你一个长度数组,然后使用Take / Skip将你想要的元素抓到你所追求的更短序列中吗?