Java8 vs C# vs Scala vs Groovy vs Ruby（コレクション編）


Java8, C#, Scala, Groovy, Rubyの比較記事です。
コレクションAPIについてあの言語のあの書き方は、この言語ではこう書く的なものです。
それぞれ覚えたけど使わないとすぐ忘れるので、まとめておきます。 
冗長な書き方とそのシンタックスシュガーもなるべく記述しときます。

(それぞれメソッドを網羅しよう＋Swiftも書こうと思ってたけど、想像以上に時間がかかったので気が向いたら追記します)

# リスト

## 作成

### Java8

```java
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
// StreamからList変換する場合
list = Stream.of("a", "b", "c").collect(Collectors.toCollection(ArrayList::new)); 

List<Integer> digits = new ArrayList<>(Arrays.asList(1, 2, 3));
```

### C# 

```csharp
var list = new List<string> { "a", "b", "c" };

var digits = new List<int> { 1, 2, 3 };
```

### Scala

```scala
// コンパニオンオブジェクトのファクトリーメソッドを利用
val list = List("a", "b", "c")

// コンス（cons）を利用, Nilは要素が0のList（この場合、List.empty[Int]でもできる）。::は要素をListの先頭に追加している
val digits = 1 :: 2 :: 3 :: Nil
```

### Groovy

```groovy
def list = ["a", "b", "c"]

def digits = [1, 2, 3]
digits = []<< 1 << 2 << 3
```

### Ruby

```ruby
list = Array["a", "b", "c"] # パターン1
list = ["a", "b", "c"]      # パターン2
list = %w(a b c)            # パターン3

# 空のリストを作成して追加  パターン4
digits = Array.new
digits.concat([1, 2, 3])
```

## シーケンシャル要素で作成

### Java8

```java
// 1から始まり10で終わる数値を作成
List<Integer> digits2 = IntStream.rangeClosed(1, 10).boxed().collect(Collectors.toList());
```

### C# 

```csharp
// 1から始まり10で終わる数値を作成
var digits2 = Enumerable.Range(1, 10).ToList<int>();
```

### Scala

```scala
// 1から始まり10で終わる数値を増分1(任意)で作成
val digits2 = List.range(1, 10, 1) // パターン1
digits2 = Range(1,10).toList       // パターン2
digits2 = (1 to 10 by 1).toList    // パターン3
```

### Groovy

```groovy
// 1から始まり10で終わる数値を作成
def digits3 = (1..10)
```

### Ruby

```ruby
# 1から始まり10で終わる数値を作成
# ちなみに1...10 は1から9
digits2 = (1..10).to_a            # パターン1
digits2 = Array(Range.new(1, 10)) # パターン2

# 増分1と明示的に指定する場合  パターン3
(1..10).step(1).to_a
```

## 同じ要素で作成

### Java8

```java
// ["a", "a", "a"]のように同じ要素で作成
Supplier<String> supplier = () -> "a";
List<String> list2 = Stream.generate(supplier).limit(3).collect(Collectors.toList());
```

### C# 

```csharp
// ["a", "a", "a"]のように同じ要素で作成
var list2 = new List<string>();
list2.AddRange(Enumerable.Repeat("a", 3));
```

### Scala

```scala
// List("a", "a", "a")のように同じ要素で作成
List.fill("a", 3)
```

### Ruby

```ruby
# ["a", "a", "a"]のように同じ要素で作成
# ただし、"a"は参照先が同じになるで破壊的メソッドを使うとすべて変わる
list2 = Array.new(3, "a")  # パターン1
list2[0].upcase!
list2[0] = "b" # 0番目の参照先が変わるので["b", "A", "A"]
["a", "a", "a"][0].upcase! # 別インスタンスなので["A", "a", "a"] 
# 上記と同じ
list2 = Array.new(3)       # パターン2
list2.fill("a")
list2[0].upcase!
```

## 追加

### Java8

```java
List<Integer> digits = new ArrayList<>(Arrays.asList(1, 2, 3));

// 先頭に要素を追加、破壊的メソッド
digits.add(0, -10); // [-10, 1, 2, 3]

// 後ろに追加、破壊的メソッド
digits.add(4); // [-10, 1, 2, 3, 4]

// リストの結合、、破壊的メソッド
digits.addAll(Arrays.asList(4, 5)); // [-10, 1, 2, 3, 4, 4, 5]
```

### C# 

```csharp
// 先頭に要素を追加。破壊的メソッド
digits.Insert(0, -10); //  {-10, 1, 2, 3}

// 後ろに追加。破壊的メソッド
digits.Add(4);  {-10, 1, 2, 3, 4}

// リストの結合、破壊的メソッド。{-10, 1, 2, 3, 4, 4, 5}
digits.AddRange(new List<int> { 4, 5 });
```

### Scala

immutableの場合

```scala
// 先頭に要素を追加、 List(1, 2, 3)
1 +: List(2, 3)

// Iterator,Iterableをmixinしているオブジェクトの要素を追加する。List(a, b, c, d)を返す
List("a", "b") ++ Seq("c", "d")
```

mutableの場合

```scala
import scala.collection.mutable._

// 空のListBufferを作成
val listBuffer = ListBuffer.empty[String]

// 後ろに追加、ListBuffer("a", "b", "c", "d")
listBuffer += "a"
listBuffer += "b"
listBuffer.append("c", "d")

val listBuffer2 = 1 +: ListBuffer(2, 3)
// 先頭に追加 listBuffer2は、ListBuffer(-1, 0, 1, 2, 3)になる
listBuffer2.prepend(-1, 0)
```

### Groovy

```groovy
// 先頭に要素を追加
digits.add(0, -1) // 破壊的メソッド [-1, 1, 2, 3]

// 後ろに追加
assert [-1, 1, 2, 3, 4]== digits.plus(4)
assert [-1, 1, 2, 3, 4]== digits + 4
assert [-1, 1, 2, 3, 4]== digits.leftShift(4) // 破壊的メソッド
assert [-1, 1, 2, 3, 4, 5]== digits << 5 // 破壊的メソッド

digits = [1, 2, 3]
// リストの結合、[1, 2, 3, 4, 5]
assert [1, 2, 3, 4, 5]== digits.plus([4, 5])
assert [1, 2, 3, 4, 5]== digits + [4, 5]
digits.addAll([4, 5]) // 破壊的メソッド [1, 2, 3, 4, 5]
```

### Ruby

```ruby
# 先頭に要素を追加、破壊的メソッド。[0, 1, 2, 3]
[1, 2, 3].unshift(0)

# 後ろに追加、破壊的メソッド。
[1, 2, 3].push(4)
[1, 2, 3] << 4

## リストの結合、 [1, 2, 3, 4, 5]
[1, 2, 3] + [4, 5] # 破壊しない 
[1, 2, 3].contact([4, 5]) # レシーバー[1, 2, 3]が書き変わる破壊メソッド
```

## 削除

### Java8

```java
// 両方とも破壊メソッド
// indexで削除
digits.remove(0);
// 引数の要素を削除
digits.remove(Integer.valueOf(1));
```

### C# 

```csharp
// 両方とも破壊メソッド
// indexで削除
digits.RemoveAt(0);
// 引数の要素を削除
digits.Remove(1);
```

### Scala

```scala
// 削除、ListBuffer(a, c, d)が返る。変数listBuffer自体には変化なし
listBuffer - "b"
```

### Groovy

```groovy
digits = [1, 1, 2, 3]
// 削除、破壊しない
assert [2, 3]== digits - 1
assert [1, 1]== digits - [2, 3]
assert [2, 3]== digits.minus(1)
assert [1, 1]== digits.minus([2, 3])
```

### Ruby

```ruby
# 削除、破壊的メソッド、["a", "c"]
list3  = %w(a b c)
list3.delete_at (1)
list3  = %w(a b c)
list3.delete("b")
```

## 取得

### Java8

```java
list.get(0);
```

### C# 

```csharp
list.ElementAt(0); // パターン1
list[0];           // パターン2      
```

### Scala

```scala
list.apply(0)  // パターン1
list(0)        // パターン2
```

### Groovy

```groovy
assert "a" == list.get(0)   // パターン1
assert "a" == list.getAt(0) // パターン2
assert "a" == list[0]       // パターン3
```

### Ruby

```ruby
list[0] 
```

## head,tail

### Java8

```java
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));

// TODO headとtailのつもりだけど、もっと簡単に書けないか？
Iterator<String> ite = list.stream().iterator();
String head = ite.next(); // a
Iterable<String> iterable = () -> ite;
List<String> tail = StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList());
tail.forEach(System.out::println); // ["b", "c"]

List<String> init = list.stream().limit(list.size() - 1).collect(Collectors.toList());
init.forEach(System.out::println); // ["a", "b"]
Optional<String> last = list.stream().reduce((a, b) -> b); // Optional[c]
```

### C# 

```csharp
list.FirstOrDefault();  // a
list.Skip(1).ToList(); // {"b", "c"}

list.Take(list.Count - 1).ToList() // {"a", "b"}
list.LastOrDefault(); // c
```

### Scala

```scala
list.head // a
list.tail // List(b, c)

list.init // List(a, b)
list.last // c
```

### Groovy

```groovy
assert "a" == list.head()
assert ["b", "c"]== list.tail()
assert ["b", "c"]==  list.drop(1)

assert ["a", "b"]== list.init()
assert ["a", "b"]== list.take(list.size() -1)
assert "c" == list.last()
assert "c" == list[-1]
```

### Ruby

```ruby
list.first        #  a
list.drop(1)      # [b, c]
list[1..-1]       # [b, c]
list.slice(1..-1) # [b, c]
list.last         # c
list[-1]          # c
```

## 繰り返し（foreach）

### Java8

```java
List<Integer> digits = new ArrayList<>(Arrays.asList(1, 2, 3));

// パターン1
digits.forEach(new Consumer<Integer>() {
    @Override
    public void accept(Integer t) {
        System.out.println(t);
    }
});
// パターン2
digits.forEach(n -> {
    System.out.println(n);
});
// パターン3
digits.forEach(n -> System.out.println(n));
// パターン4
digits.forEach(System.out::println);
```

### C# 

```csharp
var digits = new List<int> { 1, 2, 3 };
digits.ForEach(n => Console.WriteLine(n));
```

### Scala

```scala
val list = List("a", "b", "c")

list.foreach(s => println(s)) // パターン1
list.foreach(s => println(_)) // パターン2
list.foreach(println)         // パターン3
list.foreach { println }      // パターン4
```

### Groovy

```groovy
def digits = [1, 2, 3]

// パターン1
digits.each { n -> println(n) }
// パターン2
digits.each { println(it) }
```

### Ruby

```ruby
list  = %w(a b c)

list.each { |s| print(s) }
list.each do |s| print(s) end

"a".upto("c") do |i|
    puts "#{i}"
end
```

## 繰り返し（逆順）

### Java8

```java
digits.stream().collect(Collectors.toCollection(LinkedList::new)).descendingIterator().forEachRemaining(System.out::println);
```

### C# 

```csharp
// 破壊的メソッド
digits.Reverse();
digits.ForEach(n => Console.WriteLine(n));
```

### Scala

```scala
list.reverse.foreach(println)
```

### Groovy

```groovy
// 逆順のリストがほしいだけなら、reverseだけでよい
digits.reverseEach { println(it)}
```

### Ruby

```ruby
list.reverse_each { |s| print(s) }

3.downto(1) do |i|
    puts "#{i}"
end
```
## 繰り返し（index付き）

### Java8

```java
// パターン1
IntStream.range(0, digits.size()).forEach(index -> {
    System.out.println("value=" + digits.get(index));
    System.out.println("index=" + index);
});
// パターン2
AtomicInteger index = new AtomicInteger(-1);
digits.forEach(value -> {
    System.out.println("value=" + value);
    System.out.println("index=" + index.incrementAndGet());
});
```

### C# 

```csharp
// パターン1
digits.Select((n, i) => new { n, i }).ToList().ForEach(t =>
{
    Console.WriteLine("n=" + t.n);
    Console.WriteLine("i=" + t.i);
});
// パターン2
digits.Select((n, i) => 
{
    Console.WriteLine("n=" + n);
    Console.WriteLine("i=" + i);
    return new { n, i };
});
```

### Scala

```scala
list.zipWithIndex.foreach { t => println( s"${t._2}. ${t._1}" ) } // パターン1
list.zipWithIndex.foreach { case(s:String, i:Int) => println( s"${i}. ${s}" ) } // パターン2
```

### Groovy

```groovy
digits.eachWithIndex { n,index ->
    println("value=${n}")
    println("index=${index}")
}
```

### Ruby

```ruby
# indexのみ
list.each_index { |index| 
  puts "#{list[index]}" 
}

# index付き
list.each_with_index {|s, i| 
  puts "#{i}. #{s}" 
}
```

## 写像（map）

リストの各要素に処理を適用して新しいリストを返します。

### Java8

```java
List<Integer> digits2 = IntStream.rangeClosed(1, 10).boxed().collect(Collectors.toList());

// [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]を返す
// パターン1
List<Integer> mapped1 = digits2.stream().map(new Function<Integer, Integer>() {
   @Override
   public Integer apply(Integer n) {
       return n * 2;
   }
}).collect(Collectors.toList());
// パターン2
List<Integer> mapped12 = digits2.stream().map(n -> {
   return n * 2;
}).collect(Collectors.toList());
// パターン3
List<Integer> mapped3 = digits2.stream().map(n -> n * 2).collect(Collectors.toList());
```

### C# 

```csharp
var digits2 = Enumerable.Range(1, 10).ToList<int>();

// パターン１
var mapped1 = digits2.Select(delegate(int n)
{
    return n * 2;
});
// パターン２
var mapped2 = digits2.Select(n =>
{
    return n * 2;
});
// パターン３
var mapped3 = digits2.Select(n => n * 2);
// パターン４
var mapped4 = from n in digits2
              select n * 2;
// 例えば匿名型のリストに入れ替える
var mapped5 = from n in digits2
              select new {n = n};
```

### Scala

```scala
val digits = List(1, 2, 3)

// List(2, 4, 6)を返す
digits.map((n:Int) => n * 2)
digits.map(_ * 2) 
digits.map { n => n * 2 }
digits.map { _ * 2 }
```

### Groovy

```groovy
def digits3 = (1..10)

assert [2,4,6,8,10,12,14,16,18,20]== digits3.collect {n -> n * 2 }
assert [2,4,6,8,10,12,14,16,18,20]digits3.collect { it * 2 }
assert [2,4,6,8,10,12,14,16,18,20]digits3*.multiply(2)
```

### Ruby

```ruby
digits =  [1, 2, 3]

# [2, 4, 6]を返す,それぞれ「do end」でも可能
digits.map { |n| n * 2 }
digits.collect { |n| n * 2 }
```

## 写像（index付き）

### Java8

```java
// 自力であるがindexは付けられる。ここではTupleも自作。
List<Tuple> mapped4 = IntStream.range(0, digits2.size()).mapToObj(index -> new Tuple<>(index, digits2.get(index))).collect(Collectors.toList());
mapped3.forEach(System.out::println);

・・・
public class Tuple<T1, T2> {
    public final T1 _1;
    public final T2 _2;
    public Tuple(T1 arg1, T2 arg2) {
        this._1 = arg1;
        this._2 = arg2;
    }
    @Override
    public String toString() {
        return String.format("(%s, %s)", _1, _2);
    }
}
```

### C# 

```csharp
// indexも付けられるし、例えばタプル型のリストに入れ替える
var mapped6 = digits2.Select((n, index) => Tuple.Create(index, n));
```

### Scala

```scala
// indexも付けられるし、例えばタプル型のリストに入れ替える。List((0,1), (1,2), (2,3))
digits.zipWithIndex.map { case (n, index) => (index, n) }
```

### Groovy

```groovy
// indexも付けられるし、例えばタプル型のリストに入れ替える
digits3.eachWithIndex { it, index ->
    println(new Tuple(index, it))
}
```

### Ruby

```ruby
# indexも付けられるし、リストのリストを返す。[[0, 1], [1, 2], [2, 3]]
digits.map.with_index { |n, index| [index, n] }
```

## 検索

条件に合う要素があるかどうかを返します。

### Java8

* allMatchは、条件にすべての要素がmatchするかどうか。
* anyMatchは、条件に一つでもmatchする要素があるかどうか。
* noneMatchは、すべての要素が条件にmatchしなかったらtrue

```java
List<Integer> digits = new ArrayList<>(Arrays.asList(1, 2, 3));

// false
digits.stream().allMatch(n -> n % 2 == 0);
// true
digits.stream().anyMatch(n -> n % 2 == 0);
// true
digits.stream().noneMatch(n -> n == 0);

// それぞれ匿名クラスでもできる
digits.stream().allMatch(new Predicate<Integer>() {
    @Override
    public boolean test(Integer n) {
        return n % 2 == 0;
    }
});
```

### C# 

* TrueForAll, Allは、条件にすべての要素がmatchするかどうか。
* Exists, Any は、条件に一つでもmatchする要素があるかどうか。

```csharp
var digits = new List<int> { 1, 2, 3 };

// false
digits.TrueForAll(n => n % 2 == 0);
digits.All(n => n % 2 == 0);

// true
digits.Exists(n => n % 2 == 0);
digits.Any(n => n % 2 == 0);
```

### Scala

* forallは、条件にすべての要素がmatchするかどうか。
* existsは、条件に一つでもmatchする要素があるかどうか。

```scala
val digits = List(1, 2, 3)

// false
digits.forall((n:Int) => n % 2 == 0)
digits.forall(_ % 2 == 0)
digits.forall { n => n % 2 == 0 }
digits.forall { _ % 2 == 0 }

// true
digits.exists(_ % 2 == 0) 
```

### Groovy

* everyは、条件にすべての要素がmatchするかどうか。
* anyは、条件に一つでもmatchする要素があるかどうか。

```groovy
def digits = [1, 2, 3]

assert false == digits.every { it % 2 == 0 }
assert true == digits.any { it % 2 == 0 }
```

### Ruby

* all?は、条件にすべての要素がmatchするかどうか。
* any?は、条件に一つでもmatchする要素があるかどうか。
* none?は、すべての要素が条件にmatchしなかったらtrue
* one?は、条件に一つだけmatchしたらtrue

```ruby
digits = [1, 2, 3]

# それぞれ「do end」でも可能
digits.all? { |n| n.integer? }    # true
digits.any? { |n| n % 2 == 0 }    # true
digits.none? { |n| !n.integer? }  # true
digits.one? { |n| n % 2 == 0 }    # true
```

## 抽出

条件に合う要素を取り出します。

### Java8

```java
List<Integer> digits2 = IntStream.rangeClosed(1, 10).boxed().collect(Collectors.toList());

// [2,4,6,8,10]を返す
List<Integer> filtered = digits2.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());

// Optional型が返る。この場合はOptional[2]。
Optional<Integer> first = digits2.stream().filter(n -> n % 2 == 0).findFirst();

// {false=[1, 3, 5, 7, 9], true=[2, 4, 6, 8, 10]}が返る
Map<Boolean, List<Integer>> partition = digits2.stream().collect(Collectors.partitioningBy(n -> n % 2 == 0));
```

### C# 

* Where, FindAllは、条件にmatchする要素だけのリストを返します。
* Findは、条件にmatchする要素の一件目を返します。

```csharp
var digits2 = Enumerable.Range(1, 10).ToList<int>();

// [2,4,6,8,10]を返す
var fillterd = digits2.FindAll(n => n % 2 == 0); // パターン1
var filtered2 = digits2.Where(n => n % 2 == 0); // パターン2
var filtered3 = from n in digits2　// パターン3
                where n % 2 == 0
                select n; 
 
// 最初の一件
var fillterd4 = digits2.Find(n => n % 2 == 0);
```

### Scala

* filterは、条件にmatchする要素だけのリストを返します。
* findは、条件にmatchする要素の一件目を返します。
* partitionは、条件に合うリストと合わないリストを返します。

```scala
val digits2 = List.range(1, 10, 1)

// List(2,4,6,8,10)を返す
digits2.filter((n:Int) => n % 2 == 0) 
digits2.filter(_ % 2 == 0) 
digits2.filter { n => n % 2 == 0 } 
digits2.filter { _ % 2 == 0 } 

// Option型が返る。この場合はSome(2)。
digits2.find { _ % 2 == 0 } 

// (List(2,4,6,8,10), List(1,3,5,7,9))が返る
digits2.partition(_ % 2)
```

### Groovy

```groovy
def digits3 = (1..10)

assert [2, 4, 6, 8, 10]== digits3.findAll { it % 2 == 0 }
assert [2, 4, 6, 8, 10]== digits3.grep { it % 2 == 0 }

assert 2 == digits3.find { it % 2 == 0 }

assert [[2, 4, 6, 8, 10],[1, 3, 5, 7, 9]]== digits3.split { it % 2 == 0}
```

### Ruby

* find_all,selectは、条件にmatchする要素だけのリストを返します。
* find,detectは、条件にmatchする要素の一件目を返します。
* partitionは、条件に合うリストと合わないリストを返します。

```ruby
digits2 = [1..10]

# [2,4,6,8,10]を返す,rejectは逆
digits2.select { |n| n % 2 == 0 } 
digits2.find_all { |n| n % 2 == 0 } 

# 2が返る、要素がなければnil
digits2.detect { |n| n % 2 == 0 } 
digits2.find { |n| n % 2 == 0 } 

# [2,4,6,8,10], [1,3,5,7,9]が返る
even, odd = digits2.partition { |n| n % 2 == 0 } 
```

## 並び替え

### Java8

```java
 List<String> list4 = new ArrayList<>(Arrays.asList("b", "c", "a"));

 // ５パターン。[a, b, c]
 List<String> sorted1 = list4.stream().sorted(new Comparator<String>() {
     @Override
     public int compare(String s1, String s2) {
         return s1.compareTo(s2);
     }
 }).collect(Collectors.toList());
 List<String> sorted2 = list4.stream().sorted(java.util.Comparator.comparing(s -> s)).collect(Collectors.toList());
 List<String> sorted3 = list4.stream().sorted((s1, s2) -> s1.compareTo(s2)).collect(Collectors.toList());
 List<String> sorted4 = list4.stream().sorted(java.util.Comparator.comparing(s -> s)).collect(Collectors.toList());
 List<String> sorted5 = list4.stream().sorted().collect(Collectors.toList());
 
// 破壊的メソッド
 list4.sort(java.util.Comparator.naturalOrder());
```

### C# 

```csharp
var dtos = new[] 
{ 
    new { n = 2, s = "a" }, 
    new { n = 1, s = "b" }, 
    new { n = 1, s = "a" } 
 
};

// 並び替え、ThenByを使うことで複数のプロパティで決められる。降順の場合は、OrderByDescending, ThenByDescending
var sorted = dtos.OrderBy(dto => dto.n).ThenBy(dto => dto.s);
var sorted2 = from dto in dtos
              orderby dto.n, dto.s
              select dto;
```

### Scala

```scala
val list4 = List("b", "c", "a")

// List("a", "b", "c")が返る
list4.sorted
list4.sortWith( _ < _ )
```

### Groovy

```groovy
def list4 = ["b", "c", "a"]
// 破壊的メソッド
assert  ["a", "b", "c"]== list4.sort()
list4 = ["b", "c", "a"]
assert  ["a", "b", "c"]== list4.sort { it ,x  -> it.compareTo(x)}
```

### Ruby

```ruby
list4 = %w(b c a)

# ["a", "b", "c"]が返る
list4.sort
list4.sort{|a, b| a <=> b }
```

##　畳み込み

すべての要素を使って計算します。

### java8

```java
List<Integer> digits = new ArrayList<>(Arrays.asList(1, 2, 3));

 // 4 - 3 - 2 -1 = -2
int reduce = digits.stream().reduce(4, (n1, n2) -> n1 - n2);
```

### C# 

```csharp
var digits2 = Enumerable.Range(1, 10).ToList<int>();

// 畳み込み、第一引数(seed)は省略可能, seedが無ければ、digits2.Sum();と同じ
var fold = digits2.Aggregate(10, (sum, n) => sum + n);
```

### Scala

* foldLeftは、左の要素から順に処理します。
* foldRightは、右の要素から順に処理します。

```scala
val digits = List(1, 2, 3)

// 4-1-2-3=-2
digits.foldLeft(4)(_ - _) 
(4 /: digits)(_ - _)

// 3-2-1-4=-4 
digits.foldRight(4)(_ - _)
(digits :\ 4)(_ - _)
```

### Groovy

```groovy
def digits = [1, 2, 3]

// 4 - 3 - 2 - 1 = -2
assert -2 == digits.inject(4) {total, n -> total - n }
```

### Ruby

```ruby
digits = [1, 2, 3]

// 4-1-2-3=-2
digits.inject(4) {|diff, n| diff - n }
digits.inject(4, :-)
digits.reduce(4, :-)
```

## 合成 (zip/unzip)

二つのリストの同じ添字同士をまとめます。

### Java8

```java
// TODO 自作する必要がある？
```

### C# 

```csharp
var list = new List<string> { "a", "b", "c" };
var digits = new List<int> { 1, 2, 3 };

// List{("a", 1), ("b", 2), ("c", 3)} タプル型が格納されたListになる
var zipped = list.Zip(digits, (alpha, digit) => Tuple.Create(alpha, digit));

// 二つのリストに戻す
list = zipped.Select(t => t.Item1).ToList();
digits = zipped.Select(t => t.Item2).ToList();
```

### Scala

```scala
val list  = List("a", "b", "c")
val digits = List(1, 2, 3)

val zippedList = list zip digits2 // List(("a", 1), ("b", 2), ("c", 3)) タプル型が格納されたListになる

val (alphabet, number) = List.unzip(zippedList) // 二つのListに戻す
```

### Groovy

```groovy
def list = ["a", "b", "c"]
def digits = [1, 2, 3]

assert [["a", 1], ["b", 2], ["c", 3]]== [list, digits].transpose()

assert [["a", "b", "c"], [1, 2, 3]]== [["a", 1], ["b", 2], ["c", 3]].transpose()
```

### Ruby

```ruby
list  = %w(a b c)
digits =  [1, 2, 3]

zippedList = list.zip(digits) # [["a", "1"], ["b", "2"], ["c", "3"]] 配列の配列になる

list, digits = zippedList.transpose # 二つの配列に戻す
```

## 平坦化 (flatten)

入れ子になっているリストを一つのリストになるように連結して返します。

### Java8

```java
List<Integer> digits1 = new ArrayList<>(Arrays.asList(1, 2, 3));
List<Integer> digits2 = new ArrayList<>(Arrays.asList(4, 5, 6));
List<List<Integer>> nestedList = new ArrayList<>(Arrays.asList(digits1, digits2));
// [1, 2, 3, 4, 5, 6]
List<Integer> flatten = nestedList.stream().flatMap(n -> n.stream()).collect(Collectors.toList());
```

### C# 

```csharp
var nestedList = new List<List<int>> { new List<int> { 1, 2, 3 }, new List<int> { 4, 5, 6 } };
var flatList = nestedList.SelectMany(i => i); // {1, 2, 3, 4, 5, 6}
```

### Scala

```scala
val nestedList = List(List(1,2,3), List(4,5,6))
List flatten nestedList // List(1,2,3,4,5,6)
```

### Groovy

```groovy
def nestedList = [[1, 2, 3], [4, 5, 6]]
assert  [1, 2, 3, 4, 5, 6]== nestedList.flatten()
```

### Ruby

```ruby
nestedList = [ [1, 2, 3], [4, 5, 6] ]
nestedList.flatten # [1, 2, 3, 4, 5, 6]
```
## 写像 + 平坦化 (flatMap)

map + flatten

### Java8

```java
List<Integer> digits1 = new ArrayList<>(Arrays.asList(1, 2, 3));
List<Integer> digits2 = new ArrayList<>(Arrays.asList(4, 5, 6));
List<List<Integer>> nestedList = new ArrayList<>(Arrays.asList(digits1, digits2));

// [1, 2, 3, 100, 4, 5, 6, 100]
List<Integer> flatMap = nestedList.stream().flatMap(list -> {
    list.add(100);
    return list.stream();
}).collect(Collectors.toList());
```

### C# 

```csharp
var nestedList = new List<List<int>> { new List<int> { 1, 2, 3 }, new List<int> { 4, 5, 6 } };
// {1, 2, 3, 100, 4, 5, 6, 100}
var flatList = nestedList.SelectMany(l =>
{
    l.Add(100);
    return l;
});
```

### Scala

```scala
val nestedList = List(List(1,2,3), List(4,5,6))
// List(1, 2, 3, 100, 4, 5, 6, 100)
nestedList flatMap { list => list ++ Seq(100) }
```

### Groovy

```groovy
def nestedList = [[1, 2, 3], [4, 5, 6]]
assert [1, 2, 3, 100, 4, 5, 6, 100]== nestedList.collectMany { list -> list + 100 }
```

### Ruby

```ruby
nestedList = [ [1, 2, 3], [4, 5, 6] ]
# [1, 2, 3, 100, 4, 5, 6, 100]
nestedList.flat_map {|list| list << 100}
```

# セット

## 追加・取得・削除

### Java8

順序性がないHashSet

```java
Set<Integer> set = new HashSet<>(Arrays.asList(1, 2, 3));

// 追加、破壊的メソッド。[1, 2, 3, 4]
set.add(4);

// 削除、破壊的メソッド。[1, 3, 4]
set.remove(2);
```
順序性があるTreeSet

```java
// 自然順序。[1,2,3]
Set<Integer> treeSet = new TreeSet<>(Arrays.asList(2, 3, 1));

// 順序を変える。[3,2,1]
// パターン1
Set<Integer> treeSet2 = new TreeSet<>((s1, s2) -> s2.compareTo(s1));
treeSet2.addAll(Arrays.asList(2, 3, 1));
// パターン2
Set<Integer> treeSet3 = new TreeSet<>(java.util.Comparator.reverseOrder());
treeSet3.addAll(Arrays.asList(2, 3, 1));
```

### C# 

挿入順が保証されるHashSet

```csharp
var set = new HashSet<int> { 1, 2, 3 };
 
// 追加、Set[1, 2, 3, 4]を返す
set.Add(4);
 
//　削除、Set[1, 3, 4]
set.Remove(2);
```

順序性があるSortedSet

```csharp
// 自然順序、SortedSet[1, 2, 3]
var sortedSet = new SortedSet<int> { 2, 3, 1 };

// 順序変更、SortedSet[3, 2, 1]
var sortedSet2 = new SortedSet<int>(Comparer<int>.Create((a, b) => b.CompareTo(a))) { 2, 3, 1 };
var sortedSet3 = new SortedSet<int>(new FuncComparer<int>((a, b) => b.CompareTo(a))) { 2, 3, 1 }
class FuncComparer<T> : IComparer<T>
{
    private readonly Comparison<T> comparison;
    public FuncComparer(Comparison<T> comparison)
    {
        this.comparison = comparison;
    }
    public int Compare(T x, T y)
    {
        return comparison(x, y);
    }
}
```

### Scala

順序性がないHashSet

```scala
// デフォルトはimmutable

val set = Set(1, 2, 3)

// 追加、Set(1, 2, 3, 4)を返す
set + 4

//　削除、Set(1, 3, )
set - 2

// mutableにしたければ、importをする
import scala.collection.mutable.Set
val mutableSet = Set(1, 2, 3)

// 追加、削除
mutableSet += 4 // Set(1, 2, 3, 4) 
mutableSet -= 2 // Set(1, 3, 4)
```

順序性があるTreeSet

```scala
import scala.collection.immutable.TreeSet

// 自然順序、TreeSet(1, 2, 3)
val treeSet = TreeSet(2, 3, 1)

// 順序変更、TreeSet(3, 2, 1)
val sortRule = Ordering.fromLessThan[Int](_ > _)
val treeSet2 = TreeSet.empty(sortRule)
treeSet2 + (2, 3, 1)
```

### Groovy

順序性がないHashSet

```groovy
def set = new HashSet([1, 2, 3])
def set2 = new HashSet(1..3)
def set3 = [1, 2, 3] as Set
def set4 = (1..3) as Set

// 追加、破壊的メソッド。[1, 2, 3, 4]
set.add(4)

// 削除、破壊的メソッド。[1, 3, 4]
set.remove(2)
```

順序性があるTreeSet

```groovy
//　自然順序
assert [2, 3, 1] as Set == new TreeSet([2, 3, 1])

// 順序を変える
def treeSet = new TreeSet({it ,x ->
    x.compareTo(it)
} as Comparator)
treeSet.addAll([2, 3, 1])
```

### Ruby

順序性がないset

```ruby
set = Set[1, 2, 3]
set = Set.new(1, 2, 3)
set = Set.new(1..3)
set = (1..3).to_set

# 後ろに追加。破壊的メソッド、#<Set: {1, 2, 3, 4, 5}>
set << 4
set.add(5) 
set.add?(5) # 追加できなかったら、nilを返す

#　削除
set.delete(2)  #<Set: {1, 3, 4, 5}>
set.delete?(2) # nil

# まとめて追加、#<Set: {1, 3, 4, 5, 6, 7}>
set.merge(Set[5, 6, 7])

# まとめて削除、#<Set: {1, 3}>
set.subtract(Set.new(4..7))

# ブロックの結果がtrueの要素を削除、#<Set: {1}>
set.reject! { |s| s==3}
set.reject! { |s| s==3} # nil
```

順序性があるSortedSet

```ruby
# 自然順序、#<SortedSet: {1, 2, 3}>
SortedSet.new([2, 3, 1])
```

## 集合

### Java8

```java
Set<Integer> set1 = new HashSet<>(Arrays.asList(1, 2, 3));
Set<Integer> set2 = new HashSet<>(Arrays.asList(2, 3, 4));

// 積集合。二つの集合の共通要素を抽出します。破壊的メソッド。[2, 3]
set1.retainAll(set2);

set1 = new HashSet<>(Arrays.asList(1, 2, 3));
// 和集合。二つの集合のすべての要素を抽出します。破壊的メソッド。[1, 2, 3, 4]
set1.addAll(set2);

set1 = new HashSet<>(Arrays.asList(1, 2, 3));
// 差集合。左辺から右辺の要素を削除します、[1]
List<Integer> diff = new ArrayList<Integer>();
diff.addAll(set1);
diff.removeAll(set2);
```

### C# 

```csharp
// 積集合。二つの集合の共通要素を抽出します、{2, 3}
var interset = new HashSet<int> { 1, 2, 3 }.Intersect(new HashSet<int> { 2, 3, 4 });

// 和集合。二つの集合のすべての要素を抽出します、{1, 2, 3, 4}
var union = new HashSet<int> { 1, 2, 3 }.Union(new HashSet<int> { 2, 3, 4 });

// 差集合。左辺から右辺の要素を削除します、{1}
var except = new HashSet<int> { 1, 2, 3 }.Except(new HashSet<int> { 2, 3, 4 });

// 対称差。片方にだけしかない要素を抽出します。{4, 1}
var digits3 = new HashSet<int> { 1, 2, 3 };
digits3.SymmetricExceptWith(new HashSet<int> { 2, 3, 4 });
```

### Scala

```scala
// 積集合。二つの集合の共通要素を抽出します、Set(2, 3)
Set(1, 2, 3) & Set(2, 3, 4) 
Set(1, 2, 3) intersect Set(2, 3, 4)

// 和集合。二つの集合のすべての要素を抽出します、Set(1, 2, 3, 4)
Set(1, 2, 3) | Set(2, 3, 4) 
Set(1, 2, 3) union Set(2, 3, 4)

// 差集合。左辺から右辺の要素を削除します、Set(1)
Set(1, 2, 3) &~ Set(2, 3, 4) 
Set(1, 2, 3) diff Set(2, 3, 4)

// 対称差は用意されていないので自分でやる、Set(1, 4)
val s1 = Set(1, 2, 3)
val s2 = Set(2, 3, 4)
(s1 diff s2) union (s2 diff s1)
```

### Groovy

```groovy
def set1 = [1, 2, 3] as Set
def set2 = [2, 3, 4] as Set

// 積集合。二つの集合の共通要素を抽出します。
assert [2, 3] as Set== set1.intersect(set2)

set1 = new HashSet<>(Arrays.asList(1, 2, 3))
// 和集合。二つの集合のすべての要素を抽出します。
assert [1, 2, 3, 4] as Set == set1.plus(set2)

set1 = new HashSet<>(Arrays.asList(1, 2, 3))
// 差集合。左辺から右辺の要素を削除します、[1]
assert [1] as Set == set1.minus(set2)
```

### Ruby

```ruby
# 積集合。二つの集合の共通要素を抽出します、#<Set: {2, 3}>
Set[1, 2, 3] & Set[2, 3, 4]
Set[1, 2, 3].intersection(Set[2, 3, 4])

# 和集合。二つの集合のすべての要素を抽出します、#<Set: {1, 2, 3, 4}>
Set[1, 2, 3] | Set[2, 3, 4] 
Set[1, 2, 3].union(Set[2, 3, 4])

# 差集合。左辺から右辺の要素を削除します、#<Set: {1}>
Set[1, 2, 3] - Set[2, 3, 4]
Set[1, 2, 3].difference(Set[2, 3, 4])

# 対称差。片方にだけしかない要素を抽出します。#<Set: {4, 1}>
Set[1, 2, 3] ^ Set[2, 3, 4]

# 条件が同じ集合でまとめる、#<Set: {#<Set: {1, 3}>, #<Set: {2}>}>
Set[1, 2, 3].divide { |s| s % 2 == 0 }
# divideと同じだが戻り値がhash {false=>#<Set: {1, 3}>, true=>#<Set: {2}>}
Set[1, 2, 3].classify { |s| s % 2 == 0 }
```

# マップ

## 追加・取得・削除

### Java8

```java
Map<String, Integer> map = new HashMap<String, Integer>() {
    {
        put("a", 1);
        put("b", 2);
        put("c", 3);
    }
};

// 追加、破壊的メソッド
map.put("d", 4);

// 値がない場合にデフォルト値を返す
map.getOrDefault("e", 5); // 5

// 削除、破壊的メソッド。{a=1, b=2, d=4}
map.remove("c");
```

### C# 

```csharp
var map = new Dictionary<string, int>() { { "a", 1 }, { "b", 2 }, { "c", 3 }, };

// 追加。破壊的メソッド
map.Add("d", 4);
map["e"] = 5;

// 取得、値がない場合はKeyNotFoundException
var value = map["a"];	
// 値がない場合は戻り値がfalse
if (map.TryGetValue("b", out value))
{
    Console.WriteLine(value);
}

// 削除
map.Remove("c");

// SortedSetのようにkeyでソートされる 
new SortedDictionary<string, int> { { "a", 1 }, { "b", 2 } };
```

### Scala

immutableの場合

```scala
// map,map2,map3ともに同じ
val map = Map("a" -> 1, "b" -> 2, "c" -> 3) 
val map2 = Map( ("a", 1), ("b", 2), ("c", 3) ) 

// varにする必要がある
var map3 = Map.empty[String, Int]
// 設定
map3 += "a" -> 1
map3 += "b" -> 2
map3 += "c" -> 3

// 取得 （指定の要素が無ければjava.util.NoSuchElementException）
map.apply("a") // 1
map("a") // 1
// map("z") 

// 取得（Option型が返る）
map.get("a") // Some(1)
map.get("z") // None

// 取得（指定の要素がない場合はデフォルト値）
map.getOrElse("z", 0) // 0

// 他のmapと結合する、Map(e -> 5, b -> 2, d -> 4, a -> 1, c -> 3)
val newMap = map ++ Map("d" -> 4, "e" -> 5) 
```

mutableの場合

```scala
// immutableと同様 + 以下のメソッド
import scala.collection.mutable.Map

// valで良い
val immutableMap = Map.empty[String, Int]
// 追加
immutableMap += "a" -> 1
immutableMap.update("b", 2)
immutableMap("c") = 3

// 変更
immutableMap.update("b", 20)
immutableMap("c") = 30
print(immutableMap) // Map(b -> 20, a -> 1, c -> 30)

// 取得（指定の要素がない場合は追加して返す）
immutableMap.getOrElseUpdate("z",0)

// 他のmapの要素を追加する
immutableMap ++= Map("d" -> 4, "e" -> 5)
```

### Groovy

```groovy
def map = [ "a" : 1, "b" : 2, "c" : 3 ]

// 追加、破壊的メソッド
map.put("d", 4)
map["e"] = 5

// 値がない場合にデフォルト値を返す
map.withDefault{6} // 6

// 削除、破壊的メソッド。{a=1, b=2, d=4, e=5}
map.remove("c")
```

### Ruby

```ruby
map = {a: 1, b: 2, c: 3} 
map2 = {:a => 1, :b => 2, :c => 3} 
map3 = {"a" => 1, "b" => 2, "c" => 3} 

# 追加、破壊的メソッド
map2[:d] = 4
map3["d"] = 4

# 取得 
map[:a]   # 1
map3["a"] # 1
```

## 高階メソッドでKey,Valueを扱う

リストで記述したメソッドはほぼ使えるが、Key,Value形式なので少し書き方が違います。

### Java8

```java
Map<String, Integer> map = new HashMap<String, Integer>() {
    {
        put("a", 1);
        put("b", 2);
        put("c", 3);
    }
};

// パターン1
map.forEach(new BiConsumer<String, Integer>() {
    @Override
    public void accept(String key, Integer value) {
        System.out.println(String.format("key=%s", key));
        System.out.println(String.format("value=%s", value));
    }
})
// パターン2;
map.forEach((key, value) -> {
    System.out.println(String.format("key=%s", key));
    System.out.println(String.format("value=%s", value));
});
```

### C# 

```csharp
var map = new Dictionary<string, int>() { { "a", 1 }, { "b", 2 }, { "c", 3 }, };

map.ToList().ForEach(pair => {
    Console.WriteLine("key={0}", pair.Key);
    Console.WriteLine("value={0}", pair.Value);
});
var tupple = from m in map.ToList()
                       select new { key = m.Key, value = m.Value };
```

### Scala

```scala
val map = Map("a" -> 1, "b" -> 2, "c" -> 3) 

// _1にkey, _2にvalueが入る
map.foreach { 
    item => 
        println("key=" + item._1)
        println("value=" + item._2) 
}

// caseを利用して変数名を付ける
map.foreach { 
    case (key, value) => 
        println("key=" + key)
        println("value=" + value)
}

// map特有のメソッド

// keyだけを利用する、Map(a -> 1)
map.filterKeys(_ == "a")

// valueだけを利用する、Map(b -> 4, a -> 2, c -> 6)
map.mapValues(_ * 2)
```

### Groovy

```groovy
def map = [ "a" : 1, "b" : 2, "c" : 3 ]

map.forEach{key, value ->
    println("key=${key}")
    println("value=${value}")
}
```

### Ruby

```ruby
map = {a: 1, b: 2, c: 3} 

# 他のメソッドでも同じようにkey,valueが利用できる
map.each { |k, v| 
    puts "key=#{k}"
    puts "value=#{v}"
}

# map特有のメソッド

# keyだけを利用する
map.each_key { |k|  puts "key=#{k}"}

# valueだけを利用する
map.each_value { |v|  puts "value=#{v}"}
```