На большинстве языков можно бросить оба направления. Если у Вас есть реальный класс, можно бросить его к интерфейсу. Если у Вас есть интерфейс, возможно бросить к реальному классу.
Обычно Вы только хотите войти в первое направление. Так как причина - это, Вы не должны знать то, что - реальный класс, когда у Вас есть только указатель на интерфейс. Если Вы раздаете что-то как интерфейс, необходимо смочь сделать независимо от того, что Вы должны от того интерфейса. Если Вы должны для использования частей конкретного объекта не в интерфейсе, у Вас есть проблема проектирования, которая должна быть зафиксирована вместо кастинга.
Используя отличные идеи из ваших ответов, особенно ответ Ала, я в конце концов пришел к следующему:
:vnoremap <F2> d:execute 'normal i' . join(sort(split(getreg('"'))), ' ')<CR>
Отображает кнопку F2 в визуальном режиме
для удаления выделенного текста, разделения, сортировки и объединения его, а затем повторной вставки. Когда выделение занимает несколько строк, это сортирует слова во всех из них и выводит одну отсортированную строку, что я могу быстро исправить с помощью gqq
.
Я буду рад услышать предложения о том, как это можно сделать
Большое спасибо, я многому научился :)
РЕДАКТИРОВАТЬ : '
заменен на getreg ('"')
для обработки текста с символом '
в нем.
В чистом 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
Вот эквивалент в чистом 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
и т. д.
Возможно, вы предпочитаете Python:
!python -c "import sys; print ' '.join(sorted(sys.stdin.read().split()))"
Визуально выберите текст и выполните эту строку.
:!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 - печатает.