各種言語で配列(のようなもの)の最後の要素をとってくる方法を列挙しようと思う。
きっかけは、C++ の *std::rbegin(x)
。
x
の最後の要素がほしいときにx
と二度書かなければならない言語と1度で済む言語があるよなぁとか。
C言語
#define COUNTOF(x) (sizeof(x) / sizeof(*(x)))
void somefunc(){
int x[] = { 1, 2, 3 };
int last = x[COUNTOF(x)-1]
}
たぶん、これより面倒な言語あまりはないと思う。マクロまで定義して大変。
追いかけてないのでよく知らないんだけど、C11 だともっといい方法があったりするのだろうか。
C++ でも、C++14より前の場合、生の配列なら上記の方法を使うと思う。
※ 配列のサイズがゼロの場合は、そんな配列作れないので考慮する必要がない。
C++14 とそれ以降の C++
#include <iostream>
#include <vector>
void somefunc() {
int x[] = { 1, 2, 3 };
int last1 = *std::rbegin(x);
std::vector<int> y{ 1, 2, 3 };
int last2 = y.back();
}
std::rbegin()
は、C++11 の標準じゃないと思うけど、C++14 に対応していないことになっている環境でも使えることも多いと思う。boost にも同様の関数がある。
※ 配列のサイズがゼロの場合は、そんな配列作れないので考慮する必要がない。
※ vector のサイズがゼロの場合は、未定義動作かな。
#C#
class SomeClass
{
public void SomeMethod()
{
int[] x = new int[]{ 1, 2, 3 };
int last1 = x[x.Length-1];
int last2 = x.Last(); // using System.Linq; が必要
List<int> y = new List<int>{ 1, 2, 3 };
int last3 = y[y.Count-1];
int last4 = y.Last(); // using System.Linq; が必要
}
}
System.Linq
を使うと .Last()
を使うことができる。
※ 配列が空の場合は例外だと思う。
#Go言語
x := []int{1, 2, 3}
last := x[len(x)-1]
last とか back みたいなものはなくて、 len
で長さをとってきて -1
するしかない。
と思う。
※ スライスのサイズがゼロの場合は、パニック。
groovy
x=[1,2,3]
last1 = x[-1]
last2 = x.last()
last
メソッドがある。
メソッドなので括弧が必要。
負のインデックスも使える。
※ 配列が空の場合。
-
[-1]
はjava.lang.ArrayIndexOutOfBoundsException
-
.last()
はjava.util.NoSuchElementException
違う例外になるのが面白い。
#JavaScript
var x=[1,2,3]
var last=x[x.length-1]
length
はプロパティ。
最終要素のためのメソッドやプロパティはない。よね?
※ 配列が空の場合は、 undefined
を返す。
#Objective-C
#import <Foundation/Foundation.h>
void someFunc()
{
NSArray * x = @[@1, @2, @3];
NSObject * last = [x lastObject];
}
Objective-C はよく知らないんだけど、こんな感じだよね。
最後の要素をアクセスするためのメソッド lastObject
がある。
※ 配列が空の場合は、nil
を返す。
#PHP
最後の要素をとる関数 end
に副作用があるらしい。
see PHP – 配列の最後の要素の判定にend()は使わない方がいい話
see PHPで配列の最後の値を取得する
end
を使うべきかどうかはケースバイケース。PHP 難しい。
python
import numpy
x = [ 1, 2, 3 ]
last1 = x[-1]
y = numpy.asarray([1.0, 2.0, 3.0])
last2 = y[-1]
インデックスに負を与えると後ろから数える。
知っていれば簡単。
※ 配列が空の場合は IndexError: list index out of range
が発生。例外かな。
#R
x<-c(1,2,3)
last<-x[length(x)]
インデックスが 1オリジンなので、x[length(x)-1]
ではない。
※ 配列が空の場合は NULL を返す
ruby
x = [ 1, 2, 3 ]
last1 = x[-1]
last2 = x.last
負のインデックスも使えるけど、専用のメソッドもある。
私は [-1]
よりも .last
が好き。
※ 配列が空の場合は、いずれも nil
を返す。
まとめ
言語 | アクセス | 配列が空の場合 |
---|---|---|
C | x[sizeof(x)/sizeof(*x)-1] |
無理 |
C++14(配列) | *std::rbegin(x) |
xが配列なら無理 |
C++(vector) | x.back() |
たぶん未定義 |
C#(配列) | x[x.Length-1] |
例外 |
C#(配列+Linq) | x.Last() |
例外 |
C#(List) | x[x.Count-1] |
例外 |
C#(List+Linq) | x.Last() |
例外 |
Go | x[len(x)-1] |
パニック |
groovy | x[-1] |
例外 |
groovy | x.last() |
例外 |
JavaScript | x[x.length-1] |
undefined を返す |
Objective-C(NSArray) | [x lastObject] |
nil を返す |
python | x[-1] |
たぶん例外 |
R | x[length(x)] |
NULL を返す |
ruby | x[-1] |
nil を返す |
ruby | x.last |
nil を返す |
こうしてみると、C++ って特殊だなと思う。