【Python】ソートの復讐1:バブルソート
ソートの復習用の記事です。
最初なので実装も簡単なバブルソートについて書きます。
ひとまず結論
- 最悪・平均計算量: O(n2)
- Pythonでの実装例
def bubble_sort(input_arr): len_arr = len(input_arr) update_flag = True while update_flag: update_flag = False for i in range(1,len_arr): if input_arr[i-1] > input_arr[i]: input_arr[i-1], input_arr[i] = input_arr[i], input_arr[i-1] update_flag = True return input_arr
バブルソート
- 入力配列を隣接要素の比較・入れ替え操作でソートするアルゴリズム
- 名前の由来:比較・入れ替え操作により大きい/小さい要素が浮かび上がるようにみえるから(バブル:泡のように)
- 利点:アルゴリズムが単純 → 実装が容易
- 欠点:平均計算量が大きい(要素数がNの場合、最大でN2の操作が必要)
- アルゴリズムの内容:手順(小さい順に並べる場合)
- 入力配列をin、入力配列サイズをNとする
- i = 0とする
- in[i]とin[i+1]の値を比較
- もし、in[i] > in[i+1]ならば、値の入れ替えを実施
- iをインクリメント
- i < N ならば操作2に戻る
- 操作2-5で、入れ替えを行った場合は操作1に戻る
- 終了
- 入力配列をin、入力配列サイズをNとする
- N=5の配列に対して、バブルソートを実行すると以下図のような処理の流れになる
Pythonでの処理速度
- 計測環境
- 下記コードを評価に使用
- 配列サイズNを変化させて評価
import numpy as np import time def bubble_sort(input_arr): len_arr = len(input_arr) update_flag = True while update_flag: update_flag = False for i in range(1,len_arr): if input_arr[i-1] > input_arr[i]: input_arr[i-1], input_arr[i] = input_arr[i], input_arr[i-1] update_flag = True return input_arr N=10 input_arr = np.random.rand(N) st = time.time() result_arr = bubble_sort(input_arr) elapsed = time.time() - st print("Elapsed time[sec] : ", elapsed)
評価結果
配列サイズ | 100 | 1000 | 10000 |
---|---|---|---|
処理時間[sec] | 0.009 | 1.153 | 48.133 |
平均計算量が配列サイズの2乗に比例するため、配列サイズの増加量以上に処理時間が伸びている。
サイズ100→1000のときは、サイズが10倍になって処理時間が100倍になっており計算量の増加にあった処理時間の増加である。
ただし、入力配列がソートされた状態に近いほど走査回数は少なくなるため速く完了する。
まとめ
今回は、実装が簡単なバブルソートを復習しました。
関数実装は簡単ですが、評価結果からもわかるように、配列サイズの増加に対する処理時間の増加は恐ろしいものです。
配列サイズが大きいときは、別のアルゴリズムを選択するべきです。
配列サイズがちいさいときには、便利なソートアルゴリズムではないでしょうか?
以上、ありがとうございました。
【Python】総和計算は、自作が速い!?
基本的な処理でもある総和計算、Pythonだと組み込み関数やNumPyの関数などいろいろ関数で求めることができます。
結局、どれが速いのか?どれを使えばいいのか?知らなかったので、 外出自粛期間の暇つぶしに、比較してみました。
総和計算とは
- 複数の入力値の合計を求める処理
- 例
- 入力: 一日の出費(1週間) → 総和計算の結果:一週間の出費
月 | 火 | 水 | 木 | 金 | 土 | 日 |
---|---|---|---|---|---|---|
¥1,200 | ¥300 | ¥2,500 | ¥800 | ¥3,000 | ¥0 | ¥5,000 |
総和結果(一週間の出費) |
---|
¥12,800 |
既存関数の処理速度比較
単純なforループの実装を基準に、Pythonの組み込み関数sum
と、
数値計算のための拡張モジュールNumpPyのsum
関数の速度を評価します。
基準:forループによる総和計算
sum_val = 0 # 総和結果を格納する変数 for item in input_arr: # input_arrは複数の入力を格納している配列 sum_val += item
組み込み関数sum
による総和計算
# sum_valに総和結果が格納される sum_val = sum(input_arr)
NumPyのsum
関数による総和計算
import numpy as np # sum_valに総和結果が格納される sum_val = np.sum(input_arr)
計測プログラム
import time import numpy as np # Generate an input array N = 1024* 1024 * 256 # The number of elements input_arr = np.random.rand(N) print('Init : done (# of elements : ', N, ' )\n', flush=True) print('###### Simple loop summation ######') st = time.time() sum_val = 0 for item in input_arr: sum_val += item elapsed_time = time.time() - st print('\tSummation result\t: ', sum_val) print('\tElapsed time[sec]\t: ', elapsed_time) print('###### Default sum function ######') st = time.time() sum_val = sum(input_arr) elapsed_time = time.time() - st print('\tSummation result\t: ', sum_val) print('\tElapsed time[sec]\t: ', elapsed_time) print('###### NumPy sum function ######') st = time.time() sum_val = np.sum(input_arr) elapsed_time = time.time() - st print('\tSummation result\t: ', sum_val) print('\tElapsed time[sec]\t: ', elapsed_time)
処理時間比較
- 計測環境
- 計測条件
- 入力要素数:256M(=256 * 1024 * 1024)
- 入力配列:NumPy配列
関数 | 処理時間[sec] | 高速化率(基準の何倍速いか) |
---|---|---|
基準:forループ実装 | 143.377 | - |
組み込み関数sum |
64.546 | 2.22 |
NumPyのsum 関数 |
0.144 | 995.67 |
結局、簡単に思いつく既存関数だとNumPyが爆速!
基準としたPythonのforループ実装の約1000倍速い!
とりあえず、総和計算が出てきたらNumPyのsum
関数に渡せば問題ないということがわかりました!
NumPyの大半が、高速処理のためにC言語ベースで開発されているから当たり前の結果か、、
NumPyの総和計算速度に追いつく
forループの実装をベースに、自作関数でNumPyの総和計算速度に追いつくために頑張ります。
まずは、Pythonとの別れ
Pythonで実装していては、C言語で書かれた関数と同程度の速度を出すことは困難です。
そのため、forループ実装の部分を関数として切り出し、 JITコンパイルが可能であるNumbaを使って高速に処理ができる機械語に変換します。
1 . 関数として書き直す
def summation(input_arr): sum_val = 0 for item in input_arr: sum_val += item return sum_val
2 . Numbaの適用
import numba @numba.njit def summation(input_arr): sum_val = 0 for item in input_arr: sum_val += item return sum_val
NumPyとNumbaの比較
一回目の評価結果に追記する形式で行う。
- 計測環境
- 計測条件
- 入力要素数:256M(=256 * 1024 * 1024)
- 入力配列:NumPy配列
関数 | 処理時間[sec] | 高速化率(基準の何倍速いか) |
---|---|---|
基準:forループ実装 | 143.377 | - |
組み込み関数sum |
64.546 | 2.22 |
NumPyのsum 関数 |
0.144 | 995.67 |
forループ実装+Numba | 0.354 | 405.01 |
Numbaを使うだけで、NumPyのsum
関数の40%ぐらいの性能になりました!
あと、2.5倍ぐらいするとNumPyのsum
関数に勝てます!
やはり、速度を出すためにはコンパイルすることは重要ですね。
処理の並列化(マルチコアの活用)
現在のCPUは、内部に複数の演算器(コア)を持っています。
Pythonとかで単純にコードを書いて実行すると、 1コアしか使いません。
しかし、このコアを2、4個と複数利用できるようにコードを書くと 理想的には処理時間が1/2、1/4になります。
NumPyは、もちろん、複数のコアを利用できるように書かれています。
そのため、さきほどNumba化した関数もマルチコアが活かせるように 並列処理に書きかえます。
Numbaの機能の中に、処理の並列化もあるため、結構簡単に並列処理に変更できます。
- 並列処理化
@numba.njit(parallel=True) def summation_parallel( input_arr ): sum_val = 0 for i in numba.prange(len(input_arr)): sum_val += input_arr[i] return sum_val
前回からの変更点
- デコレータ@numba.jit
を@numba.njit(parallel=True)
に変更
- 関数内のfor文のレンジを表す部分をnumba.prange(len(input_arr))
に変更
- 並列処理を行うfor文は、prange
を使う必要があるみたい、、
NumPyとNumbaの比較
一回目の評価結果に追記する形式で行う。
- 計測環境
- 計測条件
- 入力要素数:256M(=256 * 1024 * 1024)
- 入力配列:NumPy配列
関数 | 処理時間[sec] | 高速化率(基準の何倍速いか) |
---|---|---|
基準:forループ実装 | 143.377 | - |
組み込み関数sum |
64.546 | 2.22 |
NumPyのsum 関数 |
0.144 | 995.67 |
forループ実装+Numba | 0.354 | 405.01 |
forループ実装+Numba(parallel) | 0.093 | 1541.68 |
Numbaの並列処理機能を利用すると、NumPyの総和計算より速くなりました!
(今回使ったPCに限った話かも、、、NumPyが遅いとは信じがたい、、、使っているコンパイラの違いとか??)
なんにせよ!
NumPyと同等以上の速度の総和計算関数が作れたので満足です!
まぁ、実際使うなら、NumPyのほうが簡単に使えるのでNumPyで十分な気がします!
最後に、計測に使ってプログラム(+Numba)
import time import numpy as np import numba @numba.njit def summation( input_arr ): sum_val = 0 for item in input_arr: sum_val += item return sum_val @numba.njit(parallel=True) def summation_parallel( input_arr ): sum_val = 0 for i in numba.prange(len(input_arr)): sum_val += input_arr[i] return sum_val N = 1024* 1024 * 256 input_arr = np.random.rand(N) print('Init : done (# of elements : ', N, ' )\n', flush=True) print('###### Simple loop summation ######') st = time.time() sum_val = 0 for item in input_arr: sum_val += item elapsed_time = time.time() - st print('\tSummation result\t: ', sum_val) print('\tElapsed time[sec]\t: ', elapsed_time) print('###### Default sum function ######') st = time.time() sum_val = sum(input_arr) elapsed_time = time.time() - st print('\tSummation result\t: ', sum_val) print('\tElapsed time[sec]\t: ', elapsed_time) print('###### Numpy sum function ######') st = time.time() sum_val = np.sum(input_arr) elapsed_time = time.time() - st print('\tSummation result\t: ', sum_val) print('\tElapsed time[sec]\t: ', elapsed_time) print('###### Simple loop summation with Numba ######') sum_val = summation(np.ones(1)) st = time.time() sum_val = summation(input_arr) elapsed_time = time.time() - st print('\tSummation result\t: ', sum_val) print('\tElapsed time[sec]\t: ', elapsed_time) print('###### Simple loop summation with Numba + parallel ######') sum_val = summation_parallel(np.ones(1)) st = time.time() sum_val = summation_parallel(input_arr) elapsed_time = time.time() - st print('\tSummation result\t: ', sum_val) print('\tElapsed time[sec]\t: ', elapsed_time)
【Counting 1-bits】高速にビット列の1を数える!
外出自粛中に、急に気になった"ビット列の1を数える"アルゴリズムの忘却録!
ビットカウント:ビット列の1を数えるとは?
population countなんかともいわれる処理で、やりたいことは簡単!
整数を2進数としてみたときに、1の出現回数を数えること!
(本当のことを書くと、レジスタに格納された64-bitだったり、32-bitだったりするビット列の中に1が出現する回数を得る処理かな、、)
例:8までの整数のビットカウント
10進数表現 | 2進数表現 | population count結果 |
---|---|---|
0 | 0000 | 0 |
1 | 0001 | 1 |
2 | 0010 | 1 |
3 | 0011 | 2 |
4 | 0100 | 1 |
5 | 0101 | 2 |
6 | 0110 | 2 |
7 | 0111 | 3 |
8 | 1000 | 1 |
最初に、結論
手書きするなら、以下のコードが速い!
(下記コードはPythonで書いたもの)
def bit_count( number ): number = (number & 0x55555555) + (number >> 1 & 0x55555555) number = (number & 0x33333333) + (number >> 2 & 0x33333333) number = (number & 0x0f0f0f0f) + (number >> 4 & 0x0f0f0f0f) number = (number & 0x00ff00ff) + (number >> 8 & 0x00ff00ff) return (number & 0x0000ffff) + (number >>16 & 0x0000ffff)
ビット演算で、分割統治法的な処理で、固定回数で32-bitの整数のビットカウントができ、高速!
複数アルゴリズムの速度比較
簡単に思いつくアルゴリズム~結論のアルゴリズムまで、3種類を比較
Straightforward method
まず、思いつくのは以下のコードでしょう。
単純に
- 最下位ビットが1である場合、カウントアップ
- 入力値を1ビット右シフト
を入力値が0になるまでループする。
count = 0 while bit_string != 0: if bit_string&1 : count += 1 bit_string = bit_string >> 1
Improved straightforward method
2つ目は、1つ目の処理を改善した方法である。
1つ目の方法では、1000000000011
のように間に0が続く場合でも、
"1"なのか"0"なのか1つずつ確認してしまう。
2つ目の下記コードで示す方法では、連続で"0"が続く場合、一気にスキップできるため、1つ目の方法より高速になる。
しかし、1111111
のように、"1"が続く入力だとあまり速度が変わらない。
count = 0 while bit_string != 0: count += 1 bit_string = bit_string & (bit_string - 1)
Optimized method
ビット演算でカウントするアルゴリズム!
ループを使わず、どんな入力でも固定回数の操作でカウントできる!
画期的なアルゴリズムです。
工学部の方とかで、ビット演算を知っている方は、図示してみるとアハ体験になると思います。
def bit_count_numba( number ): number = (number & 0x55555555) + (number >> 1 & 0x55555555) number = (number & 0x33333333) + (number >> 2 & 0x33333333) number = (number & 0x0f0f0f0f) + (number >> 4 & 0x0f0f0f0f) number = (number & 0x00ff00ff) + (number >> 8 & 0x00ff00ff) return (number & 0x0000ffff) + (number >>16 & 0x0000ffff)
速度比較
ついでに、3つ目の方法を関数にしてnumba化してさらに高速化します! (最初のコンパイル時間を省略するために計測外で一回実行するチートをしています。。。)
numbaについては、以下の記事をどうぞ!
import time from numba import njit def bit_count( number ): number = (number & 0x55555555) + (number >> 1 & 0x55555555) number = (number & 0x33333333) + (number >> 2 & 0x33333333) number = (number & 0x0f0f0f0f) + (number >> 4 & 0x0f0f0f0f) number = (number & 0x00ff00ff) + (number >> 8 & 0x00ff00ff) return (number & 0x0000ffff) + (number >>16 & 0x0000ffff) @njit def bit_count_numba( number ): number = (number & 0x55555555) + (number >> 1 & 0x55555555) number = (number & 0x33333333) + (number >> 2 & 0x33333333) number = (number & 0x0f0f0f0f) + (number >> 4 & 0x0f0f0f0f) number = (number & 0x00ff00ff) + (number >> 8 & 0x00ff00ff) return (number & 0x0000ffff) + (number >>16 & 0x0000ffff) N = 1048576 st = time.time() count = 0 for bit_string in range(N): while bit_string != 0: if bit_string&1 : count += 1 bit_string = bit_string >> 1 elapsed_time = time.time() - st print('Count: ', count) print('Elapsed time[sec] (Straghtforward) : ', elapsed_time) st = time.time() count = 0 for bit_string in range(N): while bit_string != 0: count += 1 bit_string = bit_string & (bit_string-1) elapsed_time = time.time() - st print('Count: ', count) print('Elapsed time[sec] (Improved straghtforward) : ', elapsed_time) st = time.time() count = 0 for bit_string in range(N): count += bit_count( bit_string ) elapsed_time = time.time() - st print('Count: ', count) print('Elapsed time[sec] (Optimized) : ', elapsed_time) st = time.time() count = 0 for bit_string in range(N): while bit_string != 0: if bit_string&1 : count += 1 bit_string = bit_string >> 1 elapsed_time = time.time() - st print('Elapsed time[sec] (Straghtforward) : ', elapsed_time) st = time.time() count = 0 for bit_string in range(N): while bit_string != 0: count += 1 bit_string = bit_string & (bit_string-1) elapsed_time = time.time() - st print('Elapsed time[sec] (Improved straghtforward) : ', elapsed_time) st = time.time() count = 0 for bit_string in range(N): count += bit_count( bit_string ) elapsed_time = time.time() - st print('Elapsed time[sec] (Optimized) : ', elapsed_time) bit_count_numba( 0 ) st = time.time() count = 0 for bit_string in range(N): count += bit_count_numba( bit_string ) elapsed_time = time.time() - st print('Elapsed time[sec] (Optimized + numba) : ', elapsed_time)
結果
アルゴリズム | 処理時間[sec] |
---|---|
Straightforward method | 4.581 |
Improved straightforward method | 2.794 |
Optimized method method | 1.030 |
Optimized method + numba | 0.341 |
やはり、固定回数のビット演算で行えるだけあって、3つ目の方法が一番速いですね!
そして、Pythonは遅いですね。
numbaを使うことで3倍速くなりました。 つまり、ほかの方法もnumbaを使うことで1秒を切れそうですね。
今回は、Pythonのループ処理とかを速くする話ではないのでこの辺で!
【Python】リストの初期化は[None]*n
Pythonでリストは頻繁に使うと思います。
固定長のリストの初期化は、どの方法が速いのか気になったので検証してみました。
ひとまず結論
list1 = [None] * N
この書き方が速い!(N:リスト長)
速度検証を行う記法
検証対象は以下の3通り
パターン1
list1 = [] for i in range(N): list1.append(None)
pythonを習うと最初にかけるようになるパターンかなと思い、検証パターンに採用した。
十中八九、遅いと思われる噛ませ犬。
パターン2
list2 = [None for _ in range(N) ]
リストの生成は、このワンライナーが最も速いと思っていた。。。
パターン3
list3 = [None] * N
少し前に、この記法を知りました。
速度検証
テストコード
import time # num of elements in list N = 10000000 st = time.time() list1 = [] for i in range(N): list1.append(None) elapsed1 = time.time() - st st = time.time() list2 = [ None for _ in range(N)] elapsed2 = time.time() - st st = time.time() list3 = [None] * N elapsed3 = time.time() - st print("Elapsed (Empty): ", elapsed1, " sec") print("Elapsed (One liner): ", elapsed2, " sec") print("Elapsed (Mul): ", elapsed3, " sec")
結果
パターン | 実行時間[sec] |
---|---|
1 | 0.9249 |
2 | 0.3912 |
3 | 0.0912 |
はい![None] * N
が爆速でした!
まとめ
リストを固定長で初期化するときは、[None] * N
の一択!
【Python】イテレータを知ってみる
Pythonにあるイテレータ(iterator)について書こうと思います。
存在は知っていましたが、使ったことがなかったのでよく知らない機能でした。
外出自粛中なので、これを機に使いこなせるようになろうと調べました。
イテレータ
反復して要素を取り出すことのできるインターフェイス
また、イテレータ化されたオブジェクトをイテレータオブジェクトと呼ぶそうです。
特徴
- オブジェクトのイテレータ化には
__iter__()
メソッドが必要 - イテレータオブジェクトは
__next__()
メソッドが呼ばれる度に新しい値(次の値)を返す __next__()
メソッドは、最後の値を返したあとStopIteration
例外を返すようになる- 自作するときは、終了条件を作成するときは
StopIteration
を返すように作ること
- 自作するときは、終了条件を作成するときは
__iter__()
メソッドをもつオブジェクト例
Pythonの既存オブジェクトの中で、以下のオブジェクトは__iter__()
メソッドを持ちます。
代表例なので、他にもあると思います。
- list
- tuple
- set
- dict
確認方法:イテレータオブジェクトか?
オブジェクトをobj
とすると、下記のコードで確認することができます。
hasattr(obj, '__iter__')
イテレータオブジェクトは何ができる?
ここが一番知りたいところかと思います。 しかし、多くの人が使っているんです。
最たるものが、次の例です。
例:forループ + リスト
nums = list((1,2,3)) for i in nums: print(i)
結果
1 2 3
上記例のように、for _ in リスト
の形式でforループをよく作るんじゃないでしょうか?
これが、イテレータオブジェクトを使っている例です。
forループに入るときに、リストのnums
からイテレータオブジェクトが生成されます。
イテレータオブジェクトに対して__next__()
を繰り返して、要素を一つずつ取り出します。
そして、StopIteration
例外の発生でforループを終了します。
この例を__iter__()
メソッドと__next__()
メソッドを明にして書くと、以下のコードになります。
nums = [1,2,3] nums_iter = nums.__iter__() while True: try: tmp = nums_iter.__next__() except StopIteration: break print(tmp)
結果
1 2 3
明に書くと、__iter__()
メソッドと__next__()
メソッドの意味が分かりやすくなったでしょうか?
しかし、例外処理が必要になるのでコードが長くなってしまいます。
forループ+リストを使ったほうが簡潔で読み易いです。
そのほかに、イテレータオブジェクトが潜んでいそうな場所
- 集合を扱う関数(set, max, .. etc)
forループの例以外にも、集合内の最大値を算出するmax関数などは、引数のオブジェクトをイテレータ化し処理を実行します。
つまり、イテレータ化できるようにした自作のオブジェクトも渡すことができます。
今回はここまで。
イテレータはPythonを書いている人の多くが意識せずに使っているものでした。
次は、よく出てくるジェネレータについて調べたいと思ってます。。
では!
【caps2ctrl】CapsLockキーは邪魔!Ctrlキーに変える!(windows10)
皆さんは、CapsLockキーって使ってます?
何それって人も多いんじゃないですかね? 赤枠で囲ってるキーボードのaの左のキーです。
私にとっては、たまたま指が当たって半角になったりして、イラッとさせるだけのキーです。
今回は、このCaps LockキーをCtrlキーに変更する方法を紹介します。
変更は簡単で、以下の3ステップで 問題なければ数分で終わります。
(デバイスの設定を変更する行為なので、自己責任でお願いします。)
1. レジストリ変更のためのファイル作成(caps2ctrl.reg)
下記内容の.reg
ファイルを作成してください。
私は、caps2ctrl.reg
としましたが好きな名前で構いません。
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout] "Scancode Map"=hex:00,00,00,00,00,00,00,00,02,00,00,00,1d,00,3a,00,00,00,00,00
2. caps2ctrl.regを実行
作成した.reg
ファイルをダブルクリックしてください。
すると、ユーザーアカウント制御から、
デバイスに変更を加えることを許可しましか?
と聞かれるので、はいを押してください。
その後、レジストリエディターからWarningが表示されます。
信頼しない場合は、レジストリに追加しないでください。継続しますか?
と聞かれるので、はいを押してください。
問題なければ、
正常に追加されました。
と表示されます。
3. 再起動
正常に追加されたら、再起動してください。
以上で、設定終了です。
メモ帳等でCaps + c
とCaps + v
のコピペが使えたら、正しく設定できてます。
お疲れ様でした。
【vim】これだけは覚えとけ的なコマンド
vimをエディタとして使い続けていますが、未だに慣れない未熟者です。。
vimマスターになれば、音楽を奏でるかのようにコーディングができるらしいですが、 未だにコマンドを覚えられない私には程遠い存在です。
これから少しずつコマンドを覚えていこうと思います。 まずは、最低限必要だと思ったコマンドをまとめます。
モード切替
コマンドモードへ
コマンド | 意味 |
---|---|
ESC | コマンドモードへ |
挿入モードへ
コマンド | 意味 |
---|---|
i | 挿入モードへ |
a | カーソルを右側にずらし、挿入モードへ |
o | 新しい行を挿入後、挿入モードへ |
s | カーソルの右の文字を削除後、挿入モードへ |
cc | カーソル行の文字を削除後、挿入モードへ |
ビジュアルモードへ
コマンド | 意味 |
---|---|
v | ビジュアルモードへ |
Ctrl + v | 矩形選択のビジュアルモードへ |
V | カーソルがある行を選択後、ビジュアルモードへ |
カーソル移動
ちょっとした移動
コマンド | 意味 |
---|---|
h | 右に移動 |
j | 下に移動 |
k | 上に移動 |
l | 右に移動 |
w | 次の単語の先頭に移動 |
b | 現在、または、前の単語の先頭に移動 |
e | 単語の最後の文字まで移動 |
^ | 行の頭に移動 |
$ | 行末に移動 |
% | 対応するカッコに移動 |
ウィンドウ単位の移動
コマンド | 意味 |
---|---|
H | ウィンドウの一番上の行に移動 |
M | ウィンドウの中央行に移動 |
L | ウィンドウの一番下の行に移動 |
gg | ファイルの先頭行に移動 |
G | ファイルの最終行に移動 |
Ctrl + u | ウィンドウの1/2分上の行に移動 |
Ctrl + d | ウィンドウの1/2分下の行に移動 |
Ctrl + b | ウィンドウ分上の行に移動 |
Ctrl + f | ウィンドウ分下の行に移動 |
削除
コマンド | 意味 |
---|---|
x | カーソルの右の一文字を削除 |
diw | カーソルの単語を削除 |
D | カーソル位置から行末まで削除 |
dd | カーソル行の削除 |
Undo / Redo
コマンド | 意味 |
---|---|
u | Undo |
Ctrl + r | Redo |
検索
コマンド | 意味 |
---|---|
/word | wordを検索 |
n | カーソルから次にヒットした場所に移動 |
N | カーソル以前で最も近くでヒットした場所に移動 |
コピペ
コマンド | 意味 |
---|---|
yy | カーソル行をヤンク(コピー) |
p | カーソル位置にペースト |
単語補完
コマンド | 意味 |
---|---|
Ctrl + p | 単語補完(前方探索) |
ファイル操作
コマンド | 意味 |
---|---|
:w | 上書き保存 |
:q | 閉じる |
:wq | 上書き保存後、閉じる |
:q! | 編集を反映せず閉じる |