Швидко обчисліть загальну кількість стовпців чисел


15

Я записую таблицю розмітки, яка виглядає приблизно так:

| 13/05/15 | 09:30-16:00 |  6.5 |
| 14/05/15 | 10:00-16:30 |  6.5 |
| 16/05/15 | 15:30-01:00 |  9.5 |
| 21/05/15 | 09:00-16:30 |  7.5 |
| 22/05/15 | 08:30-17:00 |  8.5 |
| 28/05/15 | 09:30-15:30 |  6   |
| 02/06/15 | 09:00-20:00 | 11   |
| 03/06/15 | 08:30-22:30 | 14   |

Я шукаю спосіб швидко обчислити загальну суму третього стовпця та вставити його в буфер. Я маю на увазі рішення, яке використовуватиме режим візуального блоку (для вибору всіх чисел) і, можливо, реєстру виразів (щоб зробити математику).

Чи можливо це зробити за допомогою нативної команди Vim? Якщо ні, чи є плагін, який може мені допомогти?


1
Ви можете подивитися цю статтю: vim.wikia.com/wiki/Using_vim_as_calculator
nobe4

Відповіді:


15

Я написав плагін: https://github.com/sk1418/HowMuch, який підтримує візуальний вибір і робить математичні обчислення.

За замовчуванням плагін підтримує три двигуни оцінки математичних виразів: Gnu bc, python та vimscript. Ви можете робити розрахунки на певному або дозволити плагіну автоматично вибрати для вас.

Це працює з вашим прикладом так:

введіть тут опис зображення

Для отримання детальної інформації прочитайте README на github.


Було б корисно, якщо ви включите у свою відповідь натискання клавіш, необхідні для вибору, підсумовування та вставки.
pdoherty926

@ pdoherty926 For details please read the README on github.Навіть якщо я наклав натиснуті клавіші для цієї проблеми тут, я не бачу, наскільки це може бути корисним, це лише 3 чи 4 комбінації клавіш. Якщо мій сценарій комусь справді потрібен, він все одно перевірить деталі.
Кент

12

Якщо ви не хочете використовувати плагіни або перейти на скрипт bash, ви можете зробити щось на зразок наступного:

  • c-V {motions} "ay скопіювати стовпець у "a
  • :let @a = substitute(@a, 'c-V c-J', '+', 'g') замініть нові рядки стовпця на +
  • ic-R=c-Raзапустіть замінений "aчерез реєстр виразів

Як варіант: зробіть запис історії виразів повторно використаним для подальших сум стовпців

  • ctrl-V {motions} y помістити стовпчик у реєстр ""
  • ictrl-R=eval(substitute(@", '\n', '+', 'g'))

Повторення для іншого стовпця:

  • ctrl-V {motion} y (без змін)
  • ictrl-R=<CR>або якщо ви зробили щось інше з реєстром виразів, прокрутіть історію за допомогою клавіші зі стрілкою вгору (або, ctrl-Pякщо ви перезавантажили її):
    ictrl-R=<up>...<up><CR>

1
З якої - то причини мені вдалося використати рішення в подвійних лапках "замість одинарних лапок 'на substituteкоманді. Чи знаєте ви, чи є причина для цього?
vappolinario

@vappolinario для мене це працює обома способами, тому, боюся, не знаю, вибачте.
Говеркуч

@Hovercouch Не могли б ви детальніше зупинитися на третьому кроці? Яким саме чином можна було б запустити заміну через регістр виразів?
pdoherty926

Як щодо створення карти: `nnoremap <cs>: s / $ / \ = eval (заміна (@ 0, '[^ 0-9]', '+', 'g')) / <cr>`
SergioAraujo

9
:r!awk '{sum+=$6} END {print "Total: "sum}' %

Пояснення:

:r ........... read (put result in this file)
! ............ external command
awk .......... external tool
{sum+=$6} .... sixth field (awk considers spaces as field separator)
END .......... at the end
{print "Total: "sum} --> string "Total: " plus your result
% ............ current file

Я намагався функцію, яка працює тут:

" This function requires you select the numbers
fun! SumVis()
    try
        let l:a_save = @a
        norm! gv"ay
        let @a = substitute(@a,'[^0-9. ]','+','g')
        exec "norm! '>o"
        exec "norm! iTotal \<c-r>=\<c-r>a\<cr>"
     finally
        let @a = l:a_save
     endtry
endfun
vnoremap <leader>s :<C-u>call SumVis()<cr>

Використовуючи наведену вище карту, все, що вам потрібно зробити після завантаження функції, це вибрати числа, які потрібно підсумовувати, і використовувати <leader>sдля підсумовування вибраної області.

Пояснення функції:

Він використовує try/finally/endtryекструктуру для збору помилок.

let l:a_save = @a .......... if whe have register 'a' we save it temporarelly
norm! gv"a  ................................... gv --> reselects and captures selection to 'register a'
let @a = substitute(@a,'[^0-9. ]','+','g') .... removes all but numbers, dots and spaces from 'register a' and puts '+' among the numbers
exec "norm! '>o"  ............................. opens new line bellow selection. see :h '>
exec "norm! iTotal: \<c-r>=\<c-r>a\<cr>" ...... insert "Total: " plus 'expression register result
let @a = l:a_save ............................. restores original 'a' register content

Якщо ви хочете спробувати цю функцію, зробіть наступне: Скопіюйте цю функцію у свій браузер і запустіть цю команду на vim, :@+ це дозволить :call SumVis()нормально використовувати .

:@+ ......... loads `+` register making the function avaiable

Для цього потрібно зробити вибір візуального блоку з ctrl+ v, скасувати вибір і нарешті викликати функцію. Або ви можете скористатися запропонованою картою, яка сама вилучає вибір перед розрахунком.



5

Зробити плагін або кодувати це у vimscript здається трохи важким. Я вірю в плагін без плагінів і гарну композицію із зовнішніми інструментами.

Ось одноразова команда на основі користувача 2571881, яка працює, навіть якщо буфер не був збережений.

:%!awk -F '|' '{print; sum+=$4}; END {print "Total: "sum}'

Якщо ви хочете зберегти цю команду для подальшого використання, ви можете назвати її:

:command! -range=% -nargs=1 SumColumn <line1>,<line2>!awk -F '|' '{print; sum+=$('<args>' + 1)} END {print "Total: "sum}'

Це працює з візуальним підбором. Якщо ви виділите кілька рядків і перейдете в командний режим, vim встановить префікс вашої команди :'<,'>, що є діапазоном рядків для візуального вибору. Отже, ви можете запустити:

:'<,'>SumColumn 3

і він підсумовує лише 3-й стовпець вибраних рядків. За замовчуванням діапазон є %, так

:SumColumn 3

підведе підсумок 3-го стовпця всіх рядків.

EDIT: Якщо ви хочете мати змогу вказати інші роздільники полів та за замовчуванням стовпчик, що відраховується до останнього, ви можете охопити команду в bashта обробити з нею аргументи, як це:

:command! -range=% -nargs=* SumColumn <line1>,<line2>!bash -c 'awk -F ${2:-|} "{print; sum+=\$(${1:-NF - 2} + 1)} END {print \"Total: \"sum}"' sumcolumn <args>

Тепер,

:SumColumn

буде рахувати останній стовпець таблиці з "|" роздільники поля,

:SumColumn 3

буде рахувати 3-й стовпець таблиці з "|" роздільники полів та

:SumColumn 3 +

буде рахувати 3-й стовпець таблиці з роздільниками поля "+".


Як можна боротися з іншими можливими роздільниками поля? Тільки для того, щоб зробити рішення більш загальним.
SergioAraujo

@ user2571881, я відредагував відповідь, показавши це.
JoL

@JoL додавання таких функцій, як SumColumnvimrc, означає, що у вашому vimrc просто є "плагіни". Сподіваємось, ви добре підтримуєте це з часом. Для мене плагіни надають документацію, поділ на значущі частини, користуючись іншими винахідливістю. Я беру участь у висхідному напрямку, що покращує дивовижні плагіни, які ніхто не встигає створити всі самостійно (крім tpope). Ви не використовуєте vim-оточуючий, vim-втікач, vim-easy-align / vim-lion, vim-unmapaired, vim-коментар, ultisnips або ft-специфічний, наприклад vim-go, vim-rails, vimtex?
Hotschke

@Hotschke Коли я приїхав сюди, я побачив питання і подумав: "ну просто труба через awk". Але потім я побачив, що прийнята відповідь була: "Ей, завантажте цей сотні плагінів LOC та встановіть його". Третя відповідь полягала в тому, що "скачайте, завантажте цей тисячу плагінів LOC та встановіть його". Це надмірно і роздуто. Навіть якщо вам потрібно було підсумовувати стовпчики не один раз у житті, це зайве. Моя відповідь має на меті показати, як ви можете це зробити за допомогою однієї команди без плагінів, без дурниць, якщо вам потрібно це зробити лише один раз, і як ви можете зробити просту команду з параметрами з неї, якщо вам потрібно це зробити часто.
JoL

@Hotschke Щоб відповісти на ваше запитання, я встановлював кожен плагін під сонцем, який виглядав віддалено прохолодно, але тоді мій vim був неймовірно повільним (читайте "трохи млявий", що нестерпно для редактора). Подивившись більше на документи vim, я зрозумів, що плагіни мені не дуже потрібні. Багато характеристик запасів були досить хорошими, і для тих, у кого не було вімі, оболонка була дорогою. Принципово (ігноруючи зроблені винятки), згідно філософії Unix, vim - це редактор, який добре взаємодіє з іншими інструментами для ОС. Я вважаю, що це спосіб найкращим чином використовувати його. З тих пір немає плагінів.
JoL

2

Якщо стовпці правильно вирівняні, це можна зробити за допомогою простого лінійки.

  1. спочатку виберіть стовпчик у візуальному режимі, як показали інші відповіді -> CTRL-V+ перемістіть курсор
  2. виберіть вибір за допомогою y
  3. type: :echo eval(join(split(@", '\_s\+'), '+'))який розбиває текст, накреслений пробілами та новими рядками, з'єднавши елемент із +символом та оцінюючи рядок.
  4. інший спосіб продовжити: замінити нові рядки +та оцінити: :echo eval(substitute(@", "\n", '+', 'g'))- eval()це найближче, що reduceми маємо.

Якщо ні, то для підрахунку полів доведеться використовувати інші трюки. Наприклад, split(getline('.'), "[ \t|]\\+")можна використовувати для розділення стовпців на рядок у масиві. Звідти це стає так просто, як:

  1. виберіть свої лінії у візуальному режимі
  2. :echo eval(join(map(getline("'<", "'>"), { -> split(v:val, "[ \t|]\\+")[2] }), '+'))

Для того, щоб позбутися магічних значень (номер поля - 1, і +), це може стати командою

:command! -range=% -nargs=+ OnField 
    \ echo { field, what -> eval(join(map(getline(<line1>, <line2>), { -> split(v:val, "[ \t|]\\+")[field-1] }), what))}(<f-args>)

Які можна використовувати з:

:OnField  3 +
:2,5OnField  3 +
:'<,'>Onfield 3 *   " after line-wise selection
....

Примітка. Тут я використовую лямбда від Vim 7.4.1xxx


1

vmap ++з плагіна vmathвід Damian Conway

  1. Встановіть плагін з github (всього 178 слотів), наприклад

    $ wget https://raw.githubusercontent.com/thoughtstream/Damian-Conway-s-Vim-Setup/master/plugin/vmath.vim -P ~/.vim/pack/manual/start/damians-tools/plugin
    
  2. Додайте картографування до свого vimrc

    vmap <silent><expr>  ++  VMATH_YankAndAnalyse()
    

    Однак я б запропонував використовувати щось інше, наприклад gA

  3. Перейдіть до третього стовпчика 2f|та виберіть стовпчик у режимі візуального блоку<C-V>G$
  4. Натисніть ++(або вибране відображення)
  5. Результати відображаються та зберігаються в регістрах (сума в s)
  6. Вставте суму з реєстру s, наприклад, з"sp

Для презентації цього плагіна дивіться відео YouTube Damian Conway, "Більше миттєво краще Vim" - OSCON 2013 (починаючи з 29 хвилини).


1

Зовнішній інструмент cli csvstatвід csvkit

:!csvstat -d '|' -H -c 4 --sum %
69.5

Коротке пояснення варіантів

  • -d DELIMITERРозмежувальний характер вхідного CSV-файла. Here |.
  • -H Вкажіть, що вхідний CSV-файл не має рядка заголовка.
  • -c COLUMNSСписок індексів або імен стовпців, що підлягають розгляду, відокремлений комами. За замовчуванням для всіх стовпців.
  • --sum Суми лише на виході.

Цей інструмент також забезпечує min, max, середню, медіану, stdev (стандартне відхилення), підраховує унікальні значення, список частих значень.

Вставити у файл с

<C-r>=system("csvstat -d '|' -H -c 4 --sum FILENAME 2> /dev/null")  

Установка

На macOS csvkit доступний через homebrew, а на Debian / Ubuntu і подібний, з яким його можна встановити $ sudo apt install csvkit.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.