Сортировать в алфавитном порядке с строчными перед заглавными? - PullRequest
0 голосов
/ 06 июля 2018

Я начал с Проекта Гутенберга "Полное собрание сочинений Уильяма Шекспира Уильяма Шекспира", текстовый файл UTF-8, доступный с http://www.gutenberg.org/ebooks/100. В PowerShell я запускал

Get-Content -Tail 50 $filename | Sort-Object -CaseSensitive

, который - я полагаю - передал последние 50 строк (то есть строк, разделенных переносами строк) файла в Sort-Object, который был настроен для сортировки по алфавиту со строками, начинающимися со строчных букв, перед строками, начинающимися с заглавных букв.

Почему выходные данные на следующем изображении (особенно в P) не сортируются в соответствии с переключателем -CaseSensitive? Что такое решение?

Link to Sort-Output Picture

Ответы [ 3 ]

0 голосов
/ 08 июля 2018

Примечание. Этот ответ посвящен общему случаю сортировки целых строк (по всем их символов, а не только по первому одному ).

Вы ищете порядковый номер сортировку , где символы сортируются численно по их кодовой точке Unicode ("значение ASCII" ) и поэтому все заглавные буквы , как группа, сортировать перед всеми строчными буквами .

Начиная с Windows PowerShell v5.1 / PowerShell Core v6.1.0, Sort-Object неизменно использует слово сортировку (с использованием инвариант культура по умолчанию, но это можно изменить с помощью параметра -Culture, где сортировка с учетом регистра просто означает, что строчная форма данной буквы непосредственно перед его заглавной формой, не все буквы вместе ; например, b сортирует до B, но оба они идут после обоих a и A (также логика обратна от порядкового регистра, где на первом месте стоят заглавные буквы ):

PS> 'B', 'b', 'A', 'a' | Sort-Object -CaseSensitive
a
A
b
B

Следовательно, для порядкового номера сортировки в настоящее время вы должны использовать .NET Framework напрямую (но обратите внимание, что расширение Sort-Object рассматривается ):

# Get the last 50 lines as a list.
[Collections.Generic.List[string]] $lines = Get-Content -Tail 50 $filename

# Sort the list in place, using ordinal sorting
$lines.Sort([StringComparer]::Ordinal)

# Output the result.
# Note that uppercase letters come first.
$lines

[StringComparer]::Ordinal возвращает объект, который реализует интерфейс [System.Collections.IComparer].

Использование этого решения в конвейере возможно, но нетривиально (массив строк отправляется один элемент):

(, (Get-Content -Tail 50 $filename)) | ForEach-Object { 
  ($lines = [Collections.Generic.List[string]] $_).Sort([StringComparer]::Ordinal)
  $lines # output the sorted lines 
}

Примечание: Как уже говорилось, это сортирует прописные буквы буквы первые .


Чтобы отсортировать все строчные буквы сначала , вам необходимо реализовать пользовательскую сортировку с помощью [System.Comparison[string] делегата , который в PowerShell может быть реализован как блок сценария ({ ... }), который принимает две входные строки и возвращает их рейтинг сортировки (-1 (или любое отрицательное значение) для меньше , 0 для равно , 1 (или любое положительное значение) для больше чем ):

$lines.Sort({ param([string]$x, [string]$y)
  # Determine the shorter of the two lengths.
  $count = if ($x.Length -lt $y.Length) { $x.Length } else { $y.Length }
  # Loop over all characters in corresponding positions.
  for ($i = 0; $i -lt $count; ++$i) {
    if ([char]::IsLower($x[$i]) -ne [char]::IsLower($y[$i])) {
      # Sort all lowercase chars. before uppercase ones.
      return (1, -1)[[char]::IsLower($x[$i])]
    } elseif ($x[$i] -ne $y[$i]) { # compare code points (numerically)
      return $x[$i] - $y[$i]
    }
    # So far the two strings compared equal, continue.
  }
  # The strings compared equal in all corresponding character positions,
  # so the difference in length, if any, is the decider (longer strings sort
  # after shorter ones).
  return $x.Length - $y.Length
})

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

0 голосов
/ 15 июля 2018

Сравнивая ответы Джейкоба и mklement0, решение Джейкоба имеет такие преимущества, как визуальная простота, интуитивность, использование конвейеров и возможность расширения до сортировки по второму символу первого слова или первому символу второго слова и т. Д. Решение mklement0 имеет Преимущества в том, чтобы быть быстрее и дать мне представление о том, как сортировать строчные и прописные буквы.

Ниже я хочу поделиться своим расширением решения Джейкоба, которое сортирует по первому символу второго слова. Не особенно полезен для Полного сочинения Шекспира, но очень полезен для таблицы, разделенной запятыми.

Function Replace-Nulls($line) {

 $dump_var = @(
      if ( !($line) ) {
           $line = [char]0 + " " + [char]0 + " [THIS WAS A LINE OF NULL WHITESPACE]"
      } # End if
      if ( !(($line.split())[1]) ) {
           $line += " " + [char]8 + " [THIS WAS A LINE WITH ONE WORD AND THE REST NULL WHITESPACE]"
      } # End if
 ) # End definition of dump_var

 return $line

} # End Replace-Nulls

echo "."
$cleaned_output = Get-Content -Tail 20 $filename | ForEach-Object{ Replace-Nulls($_) }
$cleaned_output | Sort-Object -Property {[int]((($_).split())[1])[0]}
0 голосов
/ 06 июля 2018

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

Get-Content -Tail 50 $filename | Sort-Object -Property @{E={[int]$_[0]};Ascending=$true} 

Мы можем создать выражение, используя параметр -property, равный sort-object, мы приведем к int, используя [int], а затем захватим первый символ, используя $_, чтобы взять текущую строку / строку, находящуюся в конвейере. а затем [0], чтобы взять первый символ в этой строке и отсортировать его по возрастанию.

Это обеспечивает следующий вывод.

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

 

















    DONATIONS or determine the status of compliance for any particular state
    Foundation, how to help produce our new eBooks, and how to subscribe to
    Gutenberg-tm eBooks with only a loose network of volunteer support.
    International donations are gratefully accepted, but we cannot make any
    Most people start at our Web site which has the main PG search facility:
    Project Gutenberg-tm eBooks are often created from several printed
    Please check the Project Gutenberg Web pages for current donation
    Professor Michael S. Hart was the originator of the Project Gutenberg-tm
    Section 5. General Information About Project Gutenberg-tm electronic
    This Web site includes information about Project Gutenberg-tm, including
    While we cannot and do not solicit contributions from states where we
    against accepting unsolicited donations from donors in such states who
    approach us with offers to donate.
    concept of a library of electronic works that could be freely shared
    considerable effort, much paperwork and many fees to meet and keep up
    editions, all of which are confirmed as not protected by copyright in
    have not met the solicitation requirements, we know of no prohibition
    how to make donations to the Project Gutenberg Literary Archive
    including checks, online payments and credit card donations. To donate,
    methods and addresses. Donations are accepted in a number of other ways
    necessarily keep eBooks in compliance with any particular paper edition.
    our email newsletter to hear about new eBooks.
    please visit: www.gutenberg.org/donate
    statements concerning tax treatment of donations received from outside
    the United States. U.S. laws alone swamp our small staff.
    the U.S. unless a copyright notice is included. Thus, we do not
    visit www.gutenberg.org/donate
    with anyone. For forty years, he produced and distributed Project
    www.gutenberg.org
    we have not received written confirmation of compliance. To SEND
    with these requirements. We do not solicit donations in locations where
    works.

Обновление

Сначала отсортировать строчные буквы и обрезать пустые строки. По сути, я просто умножаю число ASCII на произвольную величину, чтобы численно оно было больше, чем его строчные аналоги.

В примере текста строки не начинаются со специальных символов или знаков препинания, возможно, потребуется изменить их, чтобы правильно обрабатывать эти сценарии.

Get-Content -Tail 50 $filename | ? { -not [string]::IsNullOrEmpty($_) } | Sort-Object -Property {
    if($_[0] -cmatch "[A-Z]")
    {
        5*[int]$_[0]
    }
    else
    {
        [int]$_[0]
    } 
}

Будет выведено:

against accepting unsolicited donations from donors in such states who
approach us with offers to donate.
considerable effort, much paperwork and many fees to meet and keep up
concept of a library of electronic works that could be freely shared
editions, all of which are confirmed as not protected by copyright in
how to make donations to the Project Gutenberg Literary Archive
have not met the solicitation requirements, we know of no prohibition
including checks, online payments and credit card donations. To donate,
methods and addresses. Donations are accepted in a number of other ways
necessarily keep eBooks in compliance with any particular paper edition.
our email newsletter to hear about new eBooks.
please visit: www.gutenberg.org/donate
statements concerning tax treatment of donations received from outside
the U.S. unless a copyright notice is included. Thus, we do not
the United States. U.S. laws alone swamp our small staff.
visit www.gutenberg.org/donate
with these requirements. We do not solicit donations in locations where
works.
www.gutenberg.org
with anyone. For forty years, he produced and distributed Project
we have not received written confirmation of compliance. To SEND
DONATIONS or determine the status of compliance for any particular state
Foundation, how to help produce our new eBooks, and how to subscribe to
Gutenberg-tm eBooks with only a loose network of volunteer support.
International donations are gratefully accepted, but we cannot make any
Most people start at our Web site which has the main PG search facility:
Please check the Project Gutenberg Web pages for current donation
Professor Michael S. Hart was the originator of the Project Gutenberg-tm
Project Gutenberg-tm eBooks are often created from several printed
Section 5. General Information About Project Gutenberg-tm electronic
This Web site includes information about Project Gutenberg-tm, including
While we cannot and do not solicit contributions from states where we
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...