Powershell, своего рода встроенный набор пересечений?

StackOverflow https://stackoverflow.com/questions/1152766

  •  18-09-2019
  •  | 
  •  

Вопрос

Для какой-то игры, где нужно было бы находить анаграммы из множества незакрепленных букв, я в итоге реализовал алгоритм перестановки, чтобы найти все возможные анаграммы и отфильтровать их, если это необходимо, по известным позициям букв (-match это здорово, кстати).Но для более длинных слов это оказалось очень подверженным ошибкам, поскольку просмотр большого списка тарабарщины на самом деле не позволяет выявить нужные слова, которые были скрыты внутри.

Поэтому я подумал , что если У меня был бы большой список английских слов (должен быть где-то доступен), я мог бы просто пересеките мой список перестановок со списком правильных слов и получите (надеюсь) все реальные слова из списка перестановок.

Поскольку многие операторы в PS по-разному работают с коллекциями, я подумал, что мог бы просто сделать что-то вроде

$wordlist -contains $permlist

и верните перекресток обратно.К сожалению, это не так просто.Другими вариантами, о которых я подумал, было бы перебрать один список и выполнить -contains для каждого элемента:

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

Это, вероятно, сработало бы, но, я думаю, также очень медленно (особенно когда $wordlist является результатом gc wordlist.txt).Или я мог бы создать гигантское регулярное выражение:

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

Но это, вероятно, тоже было бы не очень быстро.Возможно, я мог бы также использовать findstr с приведенным выше гигантским регулярным выражением, но это кажется просто неправильным.

Есть ли какие-либо встроенные решения, которые я мог бы использовать и которые лучше, чем мои попытки на данный момент?В противном случае я бы, вероятно, поместил список слов в хэш-таблицу и использовал итеративный -contains подход, который тогда должен быть достаточно быстрым.

Это было полезно?

Решение

$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)

(заимствуя New-HashSet из Josh Einstein)

Предупреждение:эти методы в 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))

Очевидно, что кому-то нужно обернуть это дерьмо со статическим универсальным отражением в удобный командлет!Не волнуйся, я работаю над этим...

Другие советы

Вы могли бы проверить орфографию своего списка слов и устранить все орфографические ошибки по стандартному словарю.

С помощью ГНУ aspell установленный пакет,

 cat text.txt | aspell list

выдаст вам список всех слов с неправильным написанием.
Вы можете работать с другими словарями с aspell.


Или просто возьмите генератор анаграмм, подобный этому, создан для игроков в скрэббл.

Поисковик Revolution Word имеет два варианта;искатель анаграмм и решатель "Скрэббл".Средство поиска анаграмм берет список букв и возвращает все допустимые анаграммы, которые могут быть созданы с их использованием, относительно фиксированного списка слов.Каждая анаграмма проверяется на соответствие СВИНОМАТКИ список слов, который является списком слов, используемых в текущих международных турнирах по скрэбблу.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top