Quantcast
Channel: 配列タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 757

色々な言語で配列そのものを順序比較

$
0
0

次のJavaScriptコードの実行結果はどうなるでしょうか?

[1,11,3] > [1,2,4]

答えはfalse。配列が文字列化されて比較される。JSでの順序比較は ToPrimitive という処理を行い、その戻り値を使って比較するらしい。

あの分かりにくいECMAScript仕様書を読むと、順序比較時の ToPrimitive は以下の流れになっているようだ。

  1. @@toPrimitive メソッドを取得。取得できれば呼び出して、その結果を返す。
  2. valueOf メソッドを呼ぶ。戻り値がObjectでなければ、その結果を返す
  3. toStringメソッドを呼び、その結果を返す

ArrayにはSymbol.toPrimitiveがなく、valueOfはArray自身を返す。ArrayはObjectなので、toStringが呼ばれて文字列となるようだ。

で、他の言語ではどうなるのか気になったので色々な言語で配列の大小比較をしてみた。

Ruby

[1, 11, 3] > [1, 2, 4]

例外がスローされる。Rubyは演算子もメソッドであり、Arrayは > メソッドを実装していないのでNoMethodError。

Java

public class Hoge {
  public static void main(String[] args) {
    int[] x = new int[1];
    int[] y = new int[2];
    System.out.println(x > y);
  }
}

コンパイルエラー、エラー: 二項演算子'>'のオペランド型が不正です

Golang

package main

import "fmt"

func main() {
    a := []int{1, 11, 3}
    b := []int{1, 2, 4}
    fmt.Println(a > b)
}

コンパイルエラー、invalid operation: a > b (operator > not defined on slice)

Swift

let a = [1, 11, 3]
let b = [1, 2, 4]

print(a > b)

コンパイルエラー、error: binary operator '>' cannot be applied to two '[Int]' operands

Rust

fn main() {
    let a = [1, 11, 3];
    let b = [1, 2, 4];
    println!("{}", a > b);
}
$ ./main
true

先頭の要素から順番に比較しているようだ。

RustではOrdトレイトを実装すると大小比較が可能になる。スライスもOrdを実装している。2つのスライスの長さが異なるとコンパイルエラーになるが、可変長のvecは長さが違っても比較可能であった。

Python

>>> [1, 11, 3] > [1, 2, 4]
True

Rustと同じっぽい

PHP

<?php
echo [1,11,3] >[1,2,4];
?>
1

boolean型ないんでしたね。おそらくRust、Pythonと同じ結果でしょう

C++

#include <iostream>

int main() {
  int a[3] = {1, 2, 3};
  int b[3] = {1, 11, 3};
  std::cout << (a > b) << std::endl;
}

警告が出ます。aとbの定義位置を入れ替えると結果が変わります。これはポインタのアドレスの比較のようです。

まとめ

言語 結果
JavaScript toStringして比較
Ruby 実行時エラー
Java コンパイルエラー
Go コンパイルエラー
Swift コンパイルエラー
Rust 要素の先頭から比較
Python 要素の先頭から比較
PHP 要素の先頭から比較
C++ 不明

Viewing all articles
Browse latest Browse all 757

Trending Articles