Nhanh chóng tính tổng của một cột số


15

Tôi đang viết một bảng đánh dấu trông như thế này:

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

Tôi đang tìm cách để nhanh chóng tính toán tổng số cột thứ ba và chèn nó vào bộ đệm. Giải pháp tôi có trong đầu sẽ sử dụng chế độ khối trực quan (để chọn tất cả các số) và có thể là thanh ghi biểu thức (để làm toán).

Điều này sẽ có thể sử dụng các lệnh Vim bản địa? Nếu không, có một plugin có thể giúp tôi?


1
Bạn có thể xem bài viết này: vim.wikia.com/wiki/Using_vim_as_calculator
nobe4

Câu trả lời:


15

Tôi đã viết một plugin: https://github.com/sk1418/HowMuch hỗ trợ lựa chọn trực quan và thực hiện các phép tính toán học.

Theo mặc định, plugin hỗ trợ ba công cụ đánh giá biểu thức toán học: Gnu bc, python và vimscript. Bạn có thể thực hiện các phép tính trên một số nhất định hoặc để plugin tự động chọn một cho bạn.

Nó hoạt động với ví dụ của bạn như thế này:

nhập mô tả hình ảnh ở đây

Để biết chi tiết xin vui lòng đọc README trên github.


Sẽ rất hữu ích nếu bạn bao gồm các tổ hợp phím cần thiết để chọn, tính tổng và chèn vào câu trả lời của bạn.
pdoherty926

@ pdoherty926 For details please read the README on github.Ngay cả khi tôi đặt tổ hợp phím tôi đã nhấn cho vấn đề này ở đây, tôi không thấy nó hữu ích như thế nào, đó chỉ là 3 hoặc 4 tổ hợp phím. Nếu kịch bản của tôi thực sự cần thiết bởi ai đó, anh ấy / cô ấy sẽ kiểm tra các chi tiết nào.
Kent

11

Nếu bạn không muốn sử dụng plugin hoặc thả vào tập lệnh bash, bạn có thể làm một số thứ như sau:

  • c-V {motions} "ay sao chép cột vào "a
  • :let @a = substitute(@a, 'c-V c-J', '+', 'g') thay thế các dòng mới bằng +
  • ic-R=c-Rachạy thay thế "athông qua thanh ghi biểu thức

Ngoài ra: làm cho mục lịch sử biểu thức có thể sử dụng lại cho các cột tiếp theo

  • ctrl-V {motions} y đưa cột vào thanh ghi yank ""
  • ictrl-R=eval(substitute(@", '\n', '+', 'g'))

Lặp lại cho một cột khác:

  • ctrl-V {motion} y (không thay đổi)
  • ictrl-R=<CR>hoặc nếu bạn đã làm một cái gì đó khác với thanh ghi biểu thức, hãy duyệt qua lịch sử bằng phím mũi tên lên (hoặc với ctrl-Pnếu bạn đã ánh xạ lại nó):
    ictrl-R=<up>...<up><CR>

1
Vì một số lý do, tôi chỉ quản lý để sử dụng giải pháp của bạn với dấu ngoặc kép "thay vì dấu ngoặc đơn 'trên substitutelệnh. Bạn có biết nếu có bất kỳ lý do cho điều đó?
vappolinario

@vappolinario nó hoạt động cả hai cách đối với tôi, vì vậy tôi sợ tôi không biết, xin lỗi.
Hovercouch

@Hovercouch Bạn có thể giải thích về bước thứ ba? Làm thế nào, chính xác, một người sẽ đi về việc chạy thay thế thông qua thanh ghi biểu thức?
pdoherty926

Cách tạo bản đồ: `nnoremap <cs>: s / $ / \ = eval (thay thế (@ 0, '[^ 0-9]', '+', 'g')) / <cr>`
SergioAraujo

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

Giải trình:

: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

Tôi đã thử một chức năng hoạt động ở đây:

" 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>

Sử dụng bản đồ ở trên, tất cả những gì bạn phải làm sau khi tải vào hàm là chọn các số bạn muốn tính tổng và sử dụng <leader>sđể tổng hợp khu vực đã chọn.

Chức năng giải thích:

Nó sử dụng try/finally/endtrycấu trúc để nắm bắt lỗi.

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

Nếu bạn muốn thử chức năng này, hãy làm như sau: Sao chép chức năng này trong trình duyệt của bạn và chạy lệnh này trên vim, :@+ điều này sẽ cho phép bạn sử dụng :call SumVis()bình thường.

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

Nó cần bạn thực hiện lựa chọn khối trực quan với ctrl+ v, bỏ chọn và cuối cùng gọi hàm. Hoặc bạn có thể sử dụng bản đồ được đề xuất để tự xóa bỏ lựa chọn trước khi tính toán.



5

Làm một plugin hoặc mã hóa này trong vimscript có vẻ hơi nặng. Tôi tin vào một vim không có plugin và bố cục tốt với các công cụ bên ngoài.

Đây là lệnh 1 lần, dựa trên user2571881, hoạt động ngay cả khi bộ đệm chưa được lưu.

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

Nếu bạn muốn lưu lệnh này để sử dụng trong tương lai, bạn có thể muốn đặt tên cho nó:

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

Nó hoạt động với lựa chọn trực quan. Nếu bạn chọn một vài hàng và chuyển sang chế độ lệnh, vim sẽ thêm tiền tố vào lệnh của bạn :'<,'>, đó là phạm vi dòng cho lựa chọn trực quan. Vì vậy, bạn có thể chạy:

:'<,'>SumColumn 3

và nó sẽ chỉ tổng cột thứ 3 của các hàng được chọn. Theo mặc định, phạm vi là %, vì vậy

:SumColumn 3

sẽ tổng hợp cột thứ 3 của tất cả các dòng.

EDIT: Nếu bạn muốn có thể chỉ định các dấu tách trường khác và mặc định cột được tính đến cột cuối cùng, bạn có thể bao gồm lệnh trong bashvà xử lý các đối số với nó, như sau:

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

Hiện nay,

:SumColumn

sẽ đếm cột cuối cùng của bảng có "|" dải phân cách

:SumColumn 3

sẽ đếm cột thứ 3 của bảng có "|" dải phân cách trường và

:SumColumn 3 +

sẽ đếm cột thứ 3 của bảng có dấu phân cách trường "+".


Làm thế nào người ta có thể đối phó với các phân cách trường có thể khác? Chỉ để làm cho giải pháp chung chung hơn.
SergioAraujo

@ user2571881, tôi đã chỉnh sửa câu trả lời, cho thấy điều đó.
JoL

@JoL thêm các chức năng như SumColumnvào vimrc có nghĩa là bạn chỉ cần có 'plugin' trong vimrc của mình. Hy vọng, bạn giỏi duy trì điều này với thời gian. Đối với tôi, các plugin cung cấp tài liệu, tách thành các phần có ý nghĩa, lợi dụng sự khéo léo của người khác. Tôi đóng góp vào thượng nguồn để cải thiện các plugin tuyệt vời mà không ai có thời gian để tự tạo tất cả chúng (trừ tpope). Bạn không sử dụng vim-Surround, vim-fugitive, vim-easy-align / vim-Lion, vim-unimpaired, vim-commentary, ultisnips hoặc ft-cụ thể như vim-go, vim-rails, vimtex?
Hotschke

@Hotschke Khi tôi đến đây, tôi thấy câu hỏi và nghĩ, "tốt, chỉ cần thông qua awk." Nhưng sau đó, tôi thấy câu trả lời được chấp nhận là "này, hãy tải xuống hàng trăm plugin LỘC này và cài đặt nó." Câu trả lời thứ ba là, "này, tải xuống hàng ngàn plugin LỘC này và cài đặt nó." Đó là quá mức cần thiết và phình to. Ngay cả khi bạn cần tổng hợp các cột nhiều lần trong đời, điều đó là quá mức cần thiết. Câu trả lời của tôi là chỉ ra cách bạn có thể làm điều này trong một lệnh không bổ sung, không vô nghĩa nếu bạn chỉ cần làm điều này một lần và làm thế nào bạn có thể thực hiện một lệnh đơn giản với các tham số từ nó nếu bạn cần làm điều này thường xuyên
JoL

@Hotschke Để trả lời câu hỏi của bạn, tôi đã từng cài đặt mọi plugin dưới ánh mặt trời trông từ xa, nhưng sau đó vim của tôi rất chậm (đọc "một chút lag" không thể chấp nhận được đối với trình chỉnh sửa). Khi tìm hiểu thêm về các tài liệu vim, tôi nhận ra rằng tôi không thực sự cần các plugin. Nhiều tính năng chứng khoán là đủ tốt, và, đối với những tính năng mà vim không có, vỏ là con đường để đi. Về cơ bản (bỏ qua các ngoại lệ mà nó tạo ra), theo triết lý Unix, vim là một trình soạn thảo tương thích tốt với các công cụ hệ điều hành khác. Tôi tin rằng đó là cách để sử dụng nó tốt nhất. Không có plugin kể từ đó.
JoL

2

Nếu các cột được căn chỉnh chính xác, điều này có thể được thực hiện với một oneliner đơn giản.

  1. đầu tiên chọn cột trong chế độ hình ảnh khối thông minh như các câu trả lời khác đã chứng minh ->CTRL-V + di chuyển con trỏ
  2. chọn lựa với y
  3. loại: :echo eval(join(split(@", '\_s\+'), '+'))phân tách văn bản được kéo dài trên khoảng trắng và dòng mới, nối lại phần tử với+ ký tự và đánh giá chuỗi.
  4. một cách khác để tiến hành: thay thế các dòng mới bằng +và đánh giá: :echo eval(substitute(@", "\n", '+', 'g'))- eval()là thứ gần nhất với reducechúng ta.

Nếu không, bạn sẽ phải sử dụng các thủ thuật khác để đếm các trường. Ví dụ, split(getline('.'), "[ \t|]\\+")có thể được sử dụng để phân chia các cột từ một hàng trong mảng của bạn. Từ đó, nó trở nên đơn giản như:

  1. chọn dòng của bạn trong chế độ trực quan
  2. :echo eval(join(map(getline("'<", "'>"), { -> split(v:val, "[ \t|]\\+")[2] }), '+'))

Để loại bỏ các giá trị ma thuật (số trường - 1 và +), nó có thể trở thành một lệnh

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

Mà có thể được sử dụng với:

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

Lưu ý: Ở đây tôi sử dụng lambdas từ Vim 7.4.1xxx


1

vmap ++từ plugin vmathcủa Damian Conway

  1. Cài đặt plugin từ github (chỉ 178 sloc), vd

    $ wget https://raw.githubusercontent.com/thoughtstream/Damian-Conway-s-Vim-Setup/master/plugin/vmath.vim -P ~/.vim/pack/manual/start/damians-tools/plugin
    
  2. Thêm ánh xạ vào vimrc của bạn

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

    Tuy nhiên, tôi sẽ đề nghị sử dụng một cái gì đó khác, vd gA

  3. Di chuyển đến cột thứ ba 2f|và chọn cột trong chế độ trực quan-block<C-V>G$
  4. Nhấn ++(hoặc ánh xạ bạn đã chọn)
  5. Kết quả được hiển thị và lưu trữ trong sổ đăng ký (tổng hợp s)
  6. Chèn tổng từ đăng ký s, ví dụ với"sp

Để trình bày về plugin này, hãy xem video YouTube Damian Conway, "Vim tốt hơn ngay lập tức" - OSCON 2013 (bắt đầu từ phút 29).


1

Công cụ cli bên ngoài csvstattừ csvkit

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

Giải thích ngắn gọn về các lựa chọn

  • -d DELIMITERKý tự phân cách của tệp CSV đầu vào. Đây |.
  • -H Chỉ định rằng tệp CSV đầu vào không có hàng tiêu đề.
  • -c COLUMNSMột danh sách được phân tách bằng dấu phẩy của các chỉ mục cột hoặc tên sẽ được kiểm tra. Mặc định cho tất cả các cột.
  • --sum Chỉ có tổng đầu ra.

Công cụ này cũng cung cấp tối thiểu, tối đa, trung bình, trung bình, stdev (độ lệch chuẩn), đếm các giá trị duy nhất, danh sách các giá trị thường xuyên.

Chèn vào tập tin với

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

Cài đặt

Trên macOS csvkit có sẵn thông qua homebrew và trên Debian / Ubuntu và tương tự nó có thể được cài đặt với $ sudo apt install csvkit.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.