Сортировка слов (не строки) в VIM

На большинстве языков можно бросить оба направления. Если у Вас есть реальный класс, можно бросить его к интерфейсу. Если у Вас есть интерфейс, возможно бросить к реальному классу.

Обычно Вы только хотите войти в первое направление. Так как причина - это, Вы не должны знать то, что - реальный класс, когда у Вас есть только указатель на интерфейс. Если Вы раздаете что-то как интерфейс, необходимо смочь сделать независимо от того, что Вы должны от того интерфейса. Если Вы должны для использования частей конкретного объекта не в интерфейсе, у Вас есть проблема проектирования, которая должна быть зафиксирована вместо кастинга.

31
задан drrlvn 25 August 2009 в 14:37
поделиться

5 ответов

Используя отличные идеи из ваших ответов, особенно ответ Ала, я в конце концов пришел к следующему:

:vnoremap <F2> d:execute 'normal i' . join(sort(split(getreg('"'))), ' ')<CR>

Отображает кнопку F2 в визуальном режиме для удаления выделенного текста, разделения, сортировки и объединения его, а затем повторной вставки. Когда выделение занимает несколько строк, это сортирует слова во всех из них и выводит одну отсортированную строку, что я могу быстро исправить с помощью gqq .

Я буду рад услышать предложения о том, как это можно сделать

Большое спасибо, я многому научился :)

РЕДАКТИРОВАТЬ : ' "' заменен на getreg ('"') для обработки текста с символом ' в нем.

14
ответ дан 27 November 2019 в 22:14
поделиться

В чистом vim вы можете сделать это:

call setline('.', join(sort(split(getline('.'), ' ')), " "))

Edit

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

command! -nargs=0 -range SortWords call SortWords()
" Add a mapping, go to your string, then press vi",s
" vi" selects everything inside the quotation
" ,s calls the sorting algorithm
vmap ,s :SortWords<CR>
" Normal mode one: ,s to select the string and sort it
nmap ,s vi",s
function! SortWords()
    " Get the visual mark points
    let StartPosition = getpos("'<")
    let EndPosition = getpos("'>")

    if StartPosition[0] != EndPosition[0]
        echoerr "Range spans multiple buffers"
    elseif StartPosition[1] != EndPosition[1]
        " This is a multiple line range, probably easiest to work line wise

        " This could be made a lot more complicated and sort the whole
        " lot, but that would require thoughts on how many
        " words/characters on each line, so that can be an exercise for
        " the reader!
        for LineNum in range(StartPosition[1], EndPosition[1])
            call setline(LineNum, join(sort(split(getline('.'), ' ')), " "))
        endfor
    else
        " Single line range, sort words
        let CurrentLine = getline(StartPosition[1])

        " Split the line into the prefix, the selected bit and the suffix

        " The start bit
        if StartPosition[2] > 1
            let StartOfLine = CurrentLine[:StartPosition[2]-2]
        else
            let StartOfLine = ""
        endif
        " The end bit
        if EndPosition[2] < len(CurrentLine)
            let EndOfLine = CurrentLine[EndPosition[2]:]
        else
            let EndOfLine = ""
        endif
        " The middle bit
        let BitToSort = CurrentLine[StartPosition[2]-1:EndPosition[2]-1]

        " Move spaces at the start of the section to variable StartOfLine
        while BitToSort[0] == ' '
            let BitToSort = BitToSort[1:]
            let StartOfLine .= ' '
        endwhile
        " Move spaces at the end of the section to variable EndOfLine
        while BitToSort[len(BitToSort)-1] == ' '
            let BitToSort = BitToSort[:len(BitToSort)-2]
            let EndOfLine = ' ' . EndOfLine
        endwhile

        " Sort the middle bit
        let Sorted = join(sort(split(BitToSort, ' ')), ' ')
        " Reform the line
        let NewLine = StartOfLine . Sorted . EndOfLine
        " Write it out
        call setline(StartPosition[1], NewLine)
    endif
endfunction
23
ответ дан 27 November 2019 в 22:14
поделиться

Вот эквивалент в чистом vimscript:

 :call setline('.',join(sort(split(getline('.'),' ')),' '))

Это не короче и не проще, но если это то, что вы делаете часто, вы можете запустить его в диапазоне строк:

 :%call setline('.',join(sort(split(getline('.'),' ')),' '))

Или сделать команда

 :command -nargs=0 -range SortLine <line1>,<line2>call setline('.',join(sort(split(getline('.'),' ')),' '))

, которую можно использовать с

:SortLine
:'<,'>SortLine
:%SortLine

и т. д.

9
ответ дан 27 November 2019 в 22:14
поделиться

Возможно, вы предпочитаете Python:

!python -c "import sys; print ' '.join(sorted(sys.stdin.read().split()))"

Визуально выберите текст и выполните эту строку.

4
ответ дан 27 November 2019 в 22:14
поделиться
:!perl -ne '$,=" ";print sort split /\s+/'

Не уверен, что это требует объяснения, но если да:

perl -ne ''

запускает все, что находится внутри '' для каждой входящей строки - помещая строку в переменную по умолчанию $ _.

$,=" ";

Устанавливает список разделитель вывода на пробел. Например:

=> perl -e 'print 1,2,3'
123

=> perl -e '$,=" ";print 1,2,3'
1 2 3

=> perl -e '$,=", ";print 1,2,3'
1, 2, 3

Довольно просто.

print sort split /\s+/

Сокращенная версия:

print( sort( split( /\s+/, $_ ) ) )

($ _ в конце - переменная по умолчанию).

split - разбивает $ _ на массив с использованием заданного регулярного выражения, sort сортирует данный список, print - печатает.

6
ответ дан 27 November 2019 в 22:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: