C#展开Dictionary或Hashtable以包含Pop和Push(LIFO) [英] C# Expand Dictionary or Hashtable to include Pop and Push (LIFO)

查看:199
本文介绍了C#展开Dictionary或Hashtable以包含Pop和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?


  1. 现有项目被弹出,新推出,

  2. 将现有项目的值替换为新数据

  3. 例外

如果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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆