簡體   English   中英

在O(n)時間內更新C#鍵控集合中的所有值?

[英]Updating all values in a C# keyed collection in O(n) time?

這是我在C#中一次又一次遇到的問題,但還沒有找到一般解決方案。 在C ++ / STL中,可以使用迭代器在O(n)時間內更新映射中的所有值,而無需使用鍵來訪問每個元素。 有沒有辦法獲得與任何C#集合類似的行為,如SortedList,SortedDictionary?

我可以做點什么

foreach (int key in list.Keys)
{
    list[key] *= 3;
}

但是這需要O(n * log(n))作為搜索每個元素使用key取log(n)。

只是為了提出一個想法,我正在尋找以下內容:

SortedList<int, double> list = new SortedList<int,double>();

// Add few values fist

// E.g. first try ...
IList<double> values = list.Values;
for (int i = 0; i < values.Count; i++)
{
    values[i] *= 3;
}

// E.g. second try
foreach (KeyValuePair<int, double> kv in list)
{
    kv.Value *= 3;
}

由於List已經排序,因此應該可以遍歷它同時更新值(而不是鍵)。 從實現的角度來看,它看起來並不存在問題,但由於某種原因,似乎沒有提供功能。

此外,這不是一個簡單的情況,因為可以使用相同的方法從已知位置迭代到該范圍內的另一個修改值。

有沒有辦法在C#中使用.NET中的任何鍵控集合而不使用第三方庫?

謝謝

占道

最簡單的解決方案是將值包裝在引用類型中。

class WrappedInt { public int Value; }
Dictionary<TKey, WrappedInt> dictionary = ...;
foreach (var wrappedVal in dictionary.Values)
{
    wrappedVal.Value *= 3;
}
// or 
foreach (var wrappedVal in dictionary)
{
    wrappedVal.Value.Value *= 3;
}

這種方法適用於任何集合(列表或字典)。 在沒有包裝器的情況下通過設計實現此目的的少數集合之一是LinkedList

當然,如果您有一個非常特定的集合(由某個外部組件創建),您可以始終回退使用反射並直接在底層存儲中更改值。

SortedList<int, double> list = new SortedList<int,double>
{
    { 1, 3.14 },
    { 2, 1.618 },
};

var newList = new SortedList<int, double>(list.ToDictionary(kv => kv.Key, kv => kv.Value * 3)).Dump();

根據文檔 ,SortedList構造函數是O(n)。
.ToDictionary在引擎蓋下循環遍歷Dictionary.Add。 Dictionary.Add是O(1)時容量是足夠的

O(n)* O(1)仍然是O(n)所以你很好:-)

使用這種方法,空間要求當然加倍。

在C#中,訪問Dictionary元素接近於O(1)的恆定時間。

您可以通過調用Dictionary.Values並更新它們來獲取值列表:

foreach(var value in valuesDict.Values)
{
    // update value;
}

獲取此屬性的值( Dictionary.Values也是一個O(1)操作。

暫無
暫無

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

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