PowerShell,一种内置的交集设置?

7
对于某些需要从一堆松散的字母中找出变位词的游戏,我最终实现了一个排列算法来查找所有可能的变位词,并在必要时过滤已知的字母位置(顺便说一下,-match非常好用)。但对于较长的单词,这种方法很容易出错,因为浏览大量的无意义列表并不能揭示其中隐藏的正确单词。
所以我想,如果我有一个大型的英语单词列表(应该可以在某个地方获得),我只需将我的排列列表与正确单词列表相交,就可以从排列列表中获取(希望)所有真正的单词。
由于PS中的许多运算符与集合的工作方式不同,我认为我可以做一些类似于以下的操作:
$wordlist -contains $permlist

并获取交集。不幸的是,这并不容易。我想到的其他选项是遍历一个列表,并对每个项目执行 -contains

$permlist | ? { $wordlist -contains $_ }

我认为这种方法可能会生效,但速度非常慢(特别是当$wordlistgc wordlist.txt的结果时)。或者我可以构建一个巨大的正则表达式:

$wordlist -matches (($permlist | %{ "^$_`$" }) -join "|")

但这种方法也可能不太快。我可以尝试使用上述巨大的正则表达式和findstr,但感觉不太对。

有没有内置的解决方案比我目前的尝试更好?否则,我可能会将单词列表放入哈希表中,并使用迭代的-contains方法,这样应该足够快。

2个回答

7
$left = New-HashSet string
$left.Add("foo")
$left.Add("bar")
$right = New-HashSet string
$right.Add("bar")
$right.Add("baz")

$left.IntersectWith($right)
$left.UnionWith($right)

(从Josh Einstein借用New-HashSet)

警告:HashSet上的这些方法是就地算法,会修改原始集合。如果您想对不可变对象进行函数式转换,则需要将LINQ引入其中:

add-type system.core

$asqueryable = [system.linq.queryable].getmethods() | ? { $_.name -eq "AsQueryable" } | select -first 1
$asqueryable = $asqueryable.MakeGenericMethod([string])
$leftAsQueryable = $asqueryable.Invoke($null, (,$left))

$intersect = [system.linq.queryable].getmethods() | ? { $_.name -eq "Intersect" } | select -first 1
$intersect = $intersect.MakeGenericMethod([string])
$result = $intersect.Invoke($null, ($leftAsQueryable, $right))

显然,有人需要将这个静态-通用-反射的玩意儿包装成一个友好的cmdlet!别担心,我正在努力解决...


好的,这就是我的做法。绝对不够简洁优美。(而且绝对不能很好地适用于从命令行本身解封使用)。 - Joey
这个功能是否曾经被包装成友好的 cmdlet 并包含在标准 PS 中?虽然在 PS 5.1 中,这两种 HashSet 方法都不再起作用,而且 HashSet 类型必须通过 $left = [System.Collections.Generic.HashSet[string]]::new() 实例化。所以现在可能 HashSets 不再是一个可行的解决方案,或者至少我无法让它工作。 - Blaisem

0
你可以使用标准词典对单词列表进行拼写检查并消除所有拼写错误。
安装GNU aspell软件包后,
 cat text.txt | aspell list

将会给你一个所有拼写错误单词的列表。
你可以使用 aspell 和其他字典一起工作。


或者只需使用像这样为Scrabble玩家制作的字谜生成器

Revolution Word Finder有两个选项:一个是字谜查找器,另一个是Scrabble求解器。字谜查找器接受一个字母列表,并返回相对于固定单词列表可以创建的所有有效字谜。每个字谜都会根据SOWPODS单词列表进行有效性检查,该单词列表是当前国际Scrabble锦标赛中使用的单词列表。


您可以对单词列表进行拼写检查,使用标准字典消除所有拼写错误。这正是我尝试的。然而,这并没有告诉我如何确切地实现这一点,至少在某种程度上规避了我的问题。 - Joey
抱歉,我并不是想绕过您的拼写检查点,我已经添加了一个有关我意思的参考。我的意思是你有标准的工具来解决匹配列表的问题。 - nik
嗯,虽然这不是一个很好的"PowerShell内置"解决方案。我可能也可以强制使用Office拼写检查器,但那可能超出了我愿意为此做的范围。而且给我一个错拼单词列表并不能帮助我,因为我更需要一个正确拼写单词的列表 :) (这个游戏是http://www.kongregate.com/games/Morpheme/blocks-with-letters-on,在某些关卡中我甚至难以找到我需要构建的单词,这就是为什么我选择了暴力枚举每个排列并在结果列表中寻找单词的原因。) - Joey
您的需求非常接近于Scrabble的需求。一旦您获得了拼写错误的单词,从数据集中反转结果不应该很困难——您的关键区别已经完成。同时,我还没有检查过aspell是否可以给您提供正确拼写单词的列表——这不太可能。 - nik
关于内置需求。当您拥有打包解决方案时,为什么要在shell中尝试复杂的算法呢? - nik
好吧,反转结果会让我再次面临几乎完全相同的问题:-)。而且,如果你可以用几行代码实现它,为什么要安装它呢?我可以围绕.NET HashSet类型构建所有内容并完成它,但也许有人已经针对数组提出了一个好的解决方案,因为那些是PowerShell的默认集合。 - Joey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接