【发布时间】:2015-03-23 22:11:50
【问题描述】:
我在@Artur Udod 上采用了置换生成器解决方案回答这个问题:
Print all the possible combinations of "X" amount of characters with "X" string length (Brute Force)
我已经修改了代码以返回字符串而不是 Char 的集合,并且还能够指定是否允许在生成的排列上重复字符:
Public Shared Function PermuteCharacters(ByVal charSet As IEnumerable(Of Char),
ByVal length As Integer,
ByVal isRepetitionAllowed As Boolean) As IEnumerable(Of String)
If length = 1 Then
Return charSet.Select(Function(c As Char)
Return New String(New Char() {c})
End Function)
Else
Return PermuteCharacters(charSet, length - 1, isRepetitionAllowed).
SelectMany(Function(x As String) charSet,
Function(str As String, c As Char)
Select Case isRepetitionAllowed
Case True
Return str & c
Case Else
' Firstly I need to check if string is empty because
' String.Contains() will throw an exception on empty strings.
' This need to be fixed to avoid empty strings.
If String.IsNullOrEmpty(str) Then
Return Nothing
End If
If Not str.Contains(c) Then
Return str & c
Else
Return Nothing
End If
End Select
End Function)
End If
End Function
示例用法:
Dim permutations As IEnumerable(Of String) =
PermuteCharacters("123456789", 2, isRepetitionAllowed:=False)
问题在于,当我将重复设置为 False 时,该函数将创建、解析并返回空字符串,这会导致较大的集合或排列长度导致性能下降。
我知道我可以使用IEnumerable.Distinct() 方法来删除除一个之外的所有空字符串,但这会再次迭代整个大集合,从而导致代码本身出现更多负面性能。
我如何才能有效且正确地设计函数,同时考虑性能、创建排列集合所需的总体执行时间?
重要的是,我不认为 LINQ 的使用对性能有很大的不利影响,我将继续使用 LINQ,因为它允许开发精简的代码而不是一个普通的 Loop 所需的数千行来翻译这样的 LINQ 查询。
PS:我的次要目标是在函数上实现 Iterator 关键字以进一步提高其性能,如果有人可以说明这个问题的解决方案同时实现 Iterator 功能将非常棒(并且完美)。
【问题讨论】:
-
不能在最后加上
.Where(Function(s) Not String.IsNullOrEmpty(s))吗? -
@Bjørn-Roger Kringsjå 您建议的修改不会避免在我的
Select Case中“不需要”创建和解析空字符串,如果我附加一个WHERE子句,我还需要添加比较以返回字符串(取决于isRepetitionAllowed像.Where...( If(isRepetitionAllowed, Return Not String.IsNullOrEmpty(str), return str=str) )),而且,¿aWHEREclausule 不会在“最后”再次迭代集合?。无论如何,谢谢,但WHERE无论如何都不是一个可以利用代码性能的解决方案。 -
我删除了我的答案。我通常不会那样做。你需要改进你的问题。添加示例输入/输出。祝你好运!
-
@Plutonix 这几乎就是第一条评论所建议的。他说他对这个想法不满意。 @ElektroStudios 如果您想生成一串字符的所有组合,我会采用更传统的方法。它不仅会更快,而且您不会遇到现在遇到的问题。最多是你现在的代码量的两倍。
-
在这个问题中引起我注意的部分是 ...一个通用循环所需的数千行...。我不相信你真的是这个意思!一个获取所有可能组合的简单算法可能需要大约 20 行代码。我确实用 C 写了一个,它是 25 行(第一次尝试)。我的建议与@Taekahn 相同。因为您关心性能,所以编写自己的算法。这将比 linq 方法快得多。
标签: .net vb.net algorithm combinations permutation