用于过滤掉重复字母并重新分配给菜单alt键的可用字母的算法

时间:2011-11-22 05:53:40

标签: c# algorithm

我有一个包含许多菜单的WinForms应用程序,每个菜单平均有30个菜单项。在任何给定的菜单中,可以有多个以相同字母开头的单词。

目前,我使用一种简单的方法,通过在每个菜单项的前面添加一个&符号来创建每个项目的alt键映射。

我需要能够检测到重复的键映射(起始字母)并将其重新分配给另一个字符;尚未采取行动。获胜的角色将是最接近该词乞讨的角色。

MENU示例

  • L ist item
  • N ew Window
  • S ave文档
  • P RINT
  • P r int预览

更理想的算法足够聪明,可以查看字符串中的下一个单词,并具有附加规则。如果我可以创建一组模拟菜单的规则,例如:

FireFoxMenu

我知道火狐最有可能手动分配他们的映射 - 但我试图建设性地懒惰。

3 个答案:

答案 0 :(得分:4)

您可以将此视为http://en.wikipedia.org/wiki/Hungarian_algorithm的示例。在文章的语言中,将您的菜单项标题视为工作人员。您希望将每个工作人员分配到一个工作,其中一个工作是来自A-Z的一封信。将工作人员分配给字母(作业)的成本是菜单项中该字母的索引。这最小化了索引的总和,因此如果第一个字母都不同,最好的解决方案是使用每个菜单项的第一个字母。

当然,您通常会有比菜单项更多的字母。你可以通过发明虚拟菜单项来解决这个问题,为每个可能的字母菜单项分配收取相同的金额。

答案 1 :(得分:1)

由于您平均有30个项目,因此总是会使用多次使用的加速器字母。并且你肯定希望一个项目的字母改变你的程序的多次运行(或者更糟糕的是,在同一次运行中使用多个菜单)。

为什么不保持简单并要求每个菜单项都有一个静态的“加速器字母”属性?

答案 2 :(得分:0)

对于不耐烦的人,像我一样,在C#here中有一个非常干净的匈牙利算法实现,这里有一个快速的测试平台来解决OP的问题:

Module Module1

Sub Main()
    test1()
End Sub

Sub test1()
    Dim menus() As String =
    {"File",
     "Fiddle",
     "Forest",
     "Fangle",
     "Edit",
     "Entity",
     "Entropy",
     "Eviction",
     "View",
     "Vixen",
     "Visible",
     "Window",
     "Wait",
     "What",
     "Tools",
     "Time",
     "Total",
     "Tea"}
    Dim items As Integer = menus.GetUpperBound(0)
    Dim alphabet As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    Dim letters As Integer = alphabet.Length - 1
    Dim costs(items, letters) As Integer
    Dim cost As Integer
    Dim ch As String
    Dim o As Integer
    Dim longest As Integer = 0
    For i = 0 To items
        cost = 1
        If menus(i).Length > longest Then
            longest = menus(i).Length
        End If
        For j = 0 To menus(i).Length - 1
            ch = menus(i).Substring(j, 1)
            o = alphabet.IndexOf(ch, StringComparison.InvariantCultureIgnoreCase)
            If costs(i, o) = 0 Then ' Don't overwrite when same letter more than once in word  
                costs(i, o) = cost
                cost += 2
            End If
        Next
        For j = 0 To letters
            If costs(i, j) = 0 Then
                costs(i, j) = 99
            End If
        Next
    Next
    longest += 1
    For r = 1 To 2
        Console.Write("".PadRight(longest))
        For i = 0 To letters
            Console.Write(alphabet.Substring(i, 1).PadLeft(3))
        Next
        Console.WriteLine("")
        For i = 0 To items
            Console.Write(menus(i).PadRight(longest))
            For j = 0 To letters
                Console.Write(costs(i, j).ToString.PadLeft(3))
            Next
            Console.WriteLine("")
        Next
        If r = 1 Then
            Dim h As New HungarianAlgorithm
            Dim result() As Integer
            result = h.FindAssignments(costs)
            Console.WriteLine("Answer:")
            For i = 0 To items
                Console.WriteLine(menus(i).PadRight(longest) & alphabet.Substring(result(i), 1))
            Next
        End If
    Next r
End Sub

结束模块