Posted at

いろんな言語で数値のrangeを作って文字列でjoinした

More than 3 years have passed since last update.

次の処理を色んな言語1で書いてみた。2言語ごとに特徴が出てて面白かったです。

「range的な関数で作った1から始まる数列を、join的な関数で,区切りでくっつける。」


スクリプト言語


perl

# perl 5, version 18, subversion 2 (v5.18.2)

# 終端を含む
print(join(",", (1..10)), "\n")
#=> 1,2,3,4,5,6,7,8,9,10


php

# PHP 7.0.6

# 終端を含む
echo join(",", range(1, 10)), "\n";
#=> 1,2,3,4,5,6,7,8,9,10



  • join関数はimplode関数のエイリアスなので、implode(",", range(1, 10));でもOK。


ruby

# ruby 2.2.3

# 終端を含まない
puts (1...10).map(&:to_s).join(",")
#=> 1,2,3,4,5,6,7,8,9

# 終端を含む
puts (1..10).map(&:to_s).join(",")
#=> 1,2,3,4,5,6,7,8,9,10



  • .....がどっちがどっちかいつも不安になる。


python

# Python 3.5.1


# 終端を含まない
print(",".join(map(str, range(1, 10))))
#=> 1,2,3,4,5,6,7,8,9


  • 2系の場合、そのままだと上記のprint関数はエラーになる。 from __future__ import print_functionしておけば動く。

  • 3系のrange関数の実装は、2系だとxrange関数のほうが近いらしい。これらは遅延評価されるが、2系range関数はその範囲の値を全て最初にメモリに展開するようです。



javascript

// node v6.2.1

s1 = [...Array(10).keys()].map(n => n+1).join(',');
console.log(s1);
//=> 1,2,3,4,5,6,7,8,9,10

s2 = Array.from(Array(10).keys()).map(n => n+1).join(',')
console.log(s2);
//=> 1,2,3,4,5,6,7,8,9,10

// 終端を含まない by Underscore.js
s3 = _.range(1, 10).join(',');
console.log(s3);
//=> 1,2,3,4,5,6,7,8,9

// 終端を含まない by immutable-js
s4 = Immutable.Range(1, 10).toArray().join(',');
console.log(s4);
//=> 1,2,3,4,5,6,7,8,9


  • 素のJSで1から始まるrangeを直接取得する方法が分からなかった。。


JVM言語


java

package jp.sample;

import java.util.stream.IntStream;
import java.util.stream.Collectors;

public class Main {
public static void main(String[] args) throws Exception {
// 終端を含まない
String s1 = String.join(",", IntStream.range(1, 10).boxed().map(n -> n.toString()).collect(Collectors.toList()));
System.out.println(s1);
//=> 1,2,3,4,5,6,7,8,9

// 終端を含む
String s2 = String.join(",", IntStream.rangeClosed(1, 10).boxed().map(n -> n.toString()).collect(Collectors.toList()));
System.out.println(s2);
//=> 1,2,3,4,5,6,7,8,9,10
}
}


scala

// Scala 2.10.6


// 終端を含まない (1)
println(Range(1, 10).mkString(","))
//=> 1,2,3,4,5,6,7,8,9

// 終端を含まない (2)
println((1 until 10).mkString(","))
//=> 1,2,3,4,5,6,7,8,9

// 終端を含む
println((1 to 10).mkString(","))
//=> 1,2,3,4,5,6,7,8,9,10


clojure

; Clojure 1.8.0

(require '[clojure.string :refer [join]])

; 終端を含まない (1)
(println (join \, (range 1 10)))
;=> 1,2,3,4,5,6,7,8,9

; 終端を含まない (2) スレッディングマクロ
(->> 10 (range 1) (join \,) println)
;=> 1,2,3,4,5,6,7,8,9


CLR言語


c-sharp

// mono-3.2.8.0 (C#5, CLI4.5)

public class Hello{
public static void Main(){
// 終端を含む
System.Console.WriteLine(string.Join(",", System.Linq.Enumerable.Range(1, 10)));
//=> 1,2,3,4,5,6,7,8,9,10
}
}


f-sharp

// F# 3.0 (Open Source Edition) / mono-3.2.8.0

// 終端を含む
System.Console.WriteLine([1..10] |> List.map (fun n -> n.ToString()) |> String.concat ",")
//=> 1,2,3,4,5,6,7,8,9,10


システムプログラミング言語


rust

// rustc 1.8.0

fn main() {
// 終端を含まない
let s: String = (1..10).map(|n| n.to_string()).collect::<Vec<String>>().join(",");
println!("{}", s)
//=> 1,2,3,4,5,6,7,8,9
}


go

// go 1.4.2

package main
import (
"fmt"
"strings"
"strconv"
)

func main(){
var a []string = make([]string, 10)
for i := 0; i < 10; i++ {
a[i] = strconv.Itoa(i+1)
}
fmt.Println(strings.Join(a, ","))
//=> 1,2,3,4,5,6,7,8,9,10
}


  • rangeを直接作る方法は見つけられなかった。。


その他


swift

// Swift version 2.2

// 終端を含まない
print((1..<10).map { n in String(n) }.joinWithSeparator(","))
//=> 1,2,3,4,5,6,7,8,9

// 終端を含む
print((1...10).map { n in String(n) }.joinWithSeparator(","))
//=> 1,2,3,4,5,6,7,8,9,10


haskell

-- GHCi, version 7.10.3

-- 終端を含まない (1)
putStrLn (intercalate "," (map (\n -> show n) [1..10]))
-- => 1,2,3,4,5,6,7,8,9

-- 終端を含まない (2) リスト内包
putStrLn (intercalate "," [show n | n <- [1..10]])
-- => 1,2,3,4,5,6,7,8,9


shell

# zsh version 5.0.8

# 終端を含む
a=`seq -s"," 1 10` && echo ${a%,}
#=> 1,2,3,4,5,6,7,8,9,10


  • 変数aを使っているので、なんとなく他とやり方が違う感じがあるが、自分にはここまでしか分からなかった。

  • shellはまだまだやり方がたくさんありそう。


まとめ

メソッドをチェーンして書ける言語はどれもだいたい同じ感じになった。

rangeオブジェクトみたいなのを直接作れる言語の場合、要素の型がだいたい数値になると思うけど、それを文字列に変換(map)する一手間がある言語とない言語と。強い型付け/弱い型付けの違い以外にjoin的関数が内部でtoString()的処理をするように実装してるかどうかの違いも関わってくる。

..とか...で作られるrangeオブジェクトに終端の数値が含まれるかどうかが、言語によってまちまち。覚えるのの諦めがついた。

ScalaのmkStringは各言語のjoin的関数の上位互換だと思う。とても便利。


参考





  1. 自分が触ったことがある言語だけなので、そんなに多くはないです。 



  2. もとはJava8でrangeが作れるのか調べていて脱線した。