C#展开Dictionary或Hashtable以包含Pop和Push(LIFO) [英] C# Expand Dictionary or Hashtable to include Pop and Push (LIFO)
问题描述
寻找包含堆栈优势的结构,但只能包含一个与密钥相匹配的项目。
Looking for structure that contains the benefits of a stack but the ability to only contain one item that matches a key.
例如
数据来自从各种客户端,我只对特定客户端的最后一个数据感兴趣。所以一本字典会很好的工作。然而,我想在LIFO场景中处理来自所有客户端的数据,因此堆栈将是最好的。
For example Data comes in from various clients, I am only interested in the last piece of data from a particular client. So a dictionary would work very well. However I want to process the data from all the clients in a LIFO scenario, so a stack would be best.
任何关于组合两个的想法?
Any ideas on combining the two?
推荐答案
有几种方法来解释你想要的东西。例如,当您推送
一个已经存在的密钥的值时,会发生什么?
There are several ways to interpret what you want. For instance when you Push
a value with a key which already exists, what happens?
- 现有项目被弹出,新推出,
- 将现有项目的值替换为新数据
- 例外
如果LIFO方面是关键考虑因素,您主要需要修改堆栈
将键与数据相关联。 LinkedList
将是另一种选择。
If the LIFO aspect is the key consideration, you mainly need a modified Stack
to associate a key with the data. A LinkedList
would be another alternative.
推
在
需要将其实现为列表
中的流行 Insert(0)
和 RemoveAt(0)
。这意味着为每个操作重建底层数组。一个堆栈
反向运行:新的项目存储在阵列的端,所以它只需要定期重建。
Push
/Pop
on a List
would require implementing it as Insert(0)
and RemoveAt(0)
. This means the underlying array would be rebuilt for each and every operation. A Stack
works inversely: new items are stored at the end of the array so it only has to be rebuilt periodically.
根据数据的大小和数量,这可能并不重要。
Depending on the size and amount of data, that may not matter.
在提及字典
时,您是否也希望通过键访问变得不清楚?也就是说,您可以弹出
项,但也可以通过键检索它们。这似乎与 Stack
的性质不一致。首先,将一个Key(name)与一个项目相关联的类:
In mentioning Dictionary
it becomes unclear if you also want access by key; that is, you can Pop
items, but also retrieve them by key. That seems at odds with the nature of a Stack
. First, a class to associate a Key (name) with an item:
Class NameValuePair(Of T)
Public Property Name As String
Public Property Value As T
Public Sub New(n As String, v As T)
Name = n
Value = v
End Sub
Public Sub New(n As String)
Name = n
End Sub
Public Overrides Function ToString() As String
Return String.Format("{0} ({1})", Name, Value.ToString)
End Function
End Class
然后是类堆栈。这肯定需要根据上述的答案和其他未知数的工作。如果数据大小很小,我可能会坚持使用 List
。为了简单起见,
Then the stack-like collection. This will surely need work depending on the answers to the above and other unknowns. If the data size is small, I might stick with a List
just for simplicity.
Public Class KeyedStack(Of T)
Private myStack As Stack(Of NameValuePair(Of T))
Public Sub New()
myStack = New Stack(Of NameValuePair(Of T))
End Sub
Public Sub Push(key As String, value As T)
Dim item = myStack.FirstOrDefault(Function(k) String.Compare(k.Name, key, True) = 0)
If item IsNot Nothing Then
' replace
item.Value = value
Else
myStack.Push(New NameValuePair(Of T)(key, value))
End If
End Sub
Public Function Pop() As T
' todo check count
Dim item = myStack.Pop
Return item.Value
End Function
Public Function Peek() As T
Return myStack.Peek().Value
End Function
' ToDo: add Count, Contains, ContainsKey as needed
End Class
键不区分大小写。 Stack
提供了排序,而 NameValuePair
提供了类似字典的键。
The keys are case-insensitive. The base Stack
provides the ordering, while the NameValuePair
provides the dictionary-like key.
如果您需要推送
以将副本视为新项目(他们松动旧地方):
If you needed Push
to treat dupes as new items (they loose their old place):
' replace item as new
Public Sub PushAsNew(key As String, value As T)
Dim tmp = myStack.ToList()
Dim ndx = tmp.FindIndex(Function(k) String.Compare(k.Name, key, True) = 0)
If ndx > -1 Then
tmp.RemoveAt(ndx)
myStack = New Stack(Of NameValuePair(Of T))(tmp.ToArray.Reverse)
End If
myStack.Push(New NameValuePair(Of T)(key, value))
End Sub
由于 Stack
项目并不意味着被索引删除,所以这样做变得相当昂贵(堆栈列表到数组将阵列颠倒到新堆栈)。一个 PopByKey
方法同样昂贵。希望你不需要它。 Ulta简单测试:
Since Stack
items are not meant to be removed by index, it becomes pretty expensive to do so (stack to list to array to reversed array to new stack). A PopByKey
method is equally expensive. Hopefully, you wont need it. Ulta simple testing:
Dim data = {"Alpha", "Beta", "Gamma", "Delta", "Echo", "Ziggy"}
Dim stacker = New KeyedStack(Of String)
For Each s As String In data
stacker.Push(s(0), s)
Next
' result == Z, E, D, G, B, A order
stacker.Push("a", "Apple")
' item(5) is now {A, Apple} (key case ignored)
Dim item = stacker.Pop
' item == "Ziggy"
item = stacker.PopKey("g")
' new contents == E, D, B, A
' item == "Gamma"
stacker.PushAsNew("B", "Bottle")
' new contents == B, E, D, A
这篇关于C#展开Dictionary或Hashtable以包含Pop和Push(LIFO)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!