# Collection操作：逆引き（Python, JavaScript）

Collection系操作方法の逆引きメモ集

• Javascript
• Python

• 破壊的 OR 非破壊的

## 破壊的・非破壊的

メソッド呼び出しで前の状態を壊して、別の状態にしてしまう。

メソッド呼び出しで前の状態に変更を加えず、新しいオブジェクトを生成してそれを返却する。

## 要素数を知りたい

【Js】Array.length

```[1,2,3].length; // 3
```

【Python】len(s)

```len([1,2,3]) # 3

import numpy as np
arr = [1, 2, 3]
matrix = [[1, 2, 3], [4, 5, 6]]
print('len={}'.format(len(arr))) # len=3
print('len={}'.format(len(matrix))) # len=2

np_arr = np.array(arr)
np_matrix = np.array(matrix)
print('len={}, size={}, shape={}'.format(len(np_arr), np_arr.size, np_arr.shape)) # len=3, size=3, shape=(3,)
print('len={}, size={}, shape={}'.format(len(np_matrix), np_matrix.size, np_matrix.shape)) # len=2, size=6, shape=(2, 3)
```

## 配列の連結

【Js】[非破壊] Array Array.prototype.concat()

```const a = [1,2,3]
const b = [4,5]
const c = a.concat(b)
console.log('a=', a); // a= [ 1, 2, 3 ]
console.log('b=', b); // b= [ 4, 5 ]
console.log('c=', c); // c= [ 1, 2, 3, 4, 5 ]
```

【Python】[破壊的] array.extend(iterable)

```a = [1,2,3]
b = [4,5]
c = a.extend(b)
print('a=', a) # a= [1, 2, 3, 4, 5]　←　破壊！
print('b=', b) # b= [4, 5]
print('c=', c) # c= None
```

【Python】[非破壊] s + t

```a = [1,2,3]
b = [4,5]
c = a + b
print('a=', a) # a= [1, 2, 3]
print('b=', b) # b= [4, 5]
print('c=', c) # c= [1, 2, 3, 4, 5]
```

【Python:numpy】[非破壊] concatenate((a1, a2, ...), axis=0, out=None)

```import numpy as np
np_a = np.array([1,2,3])
np_b = np.array([4,5])
np_c = np.concatenate((np_a, np_b), axis=0)
print('np_a=', np_a) # np_a= [1 2 3]
print('np_b=', np_b) # np_b= [4 5]
print('np_c=', np_c) # np_c= [1 2 3 4 5]
```

## 配列のすべての要素が通るかどうかをテスト

```const a = [1,2,3,4,5]
const b = [2,3,4,5,6]
console.log(a.every(e => e < 6)); // true
console.log(b.every(e => e < 6)); // false
```

【Python】[非破壊] all(iterable)

```a = [1,2,3,4,5]
b = [2,3,4,5,6]
print(all(e < 6 for e in a)) # True
print(a) # [1, 2, 3, 4, 5]
print(all(e < 6 for e in b)) # False
print(b) # [2, 3, 4, 5, 6]
```

【Python:numpy】[非破壊] numpy.all(a, axis=None, out=None, keepdims)

```a = np.array([0,1,2,3,4,5])
print(a) # [0 1 2 3 4 5]
print(a.astype(np.bool)) # [False  True  True  True  True  True]
print(a < 6) # [ True  True  True  True  True  True]
print(all(e < 6 for e in a)) # True
print((a < 6).all()) # True
print(np.all(a < 6)) # True

b = np.array([2,3,4,5,6])
print(b) # [2 3 4 5 6]
print(b.astype(np.bool)) # [ True  True  True  True  True]
print(b < 6) # [ True  True  True  True False]
print(all(e < 6 for e in b)) # False
print((b < 6).all()) # False
print(np.all(b < 6)) # False
```

## 引数として与えられたテスト関数を各配列要素に対して実行し、それに合格したすべての配列要素からなる新しい配列を生成します

• 与えられた callback 関数を配列の各要素に対して一度ずつ呼び出し、callback が真の値を返したすべての値からなる新しい配列を生成します。
```const a = [1,2,3,4,5]
const b = [2,3,4,5,6]
console.log(a.filter(e => e < 6)); // [ 1, 2, 3, 4, 5 ]
console.log(b.filter(e => e < 6)); // [ 2, 3, 4, 5 ]
console.log(b); // [ 2, 3, 4, 5, 6 ]
console.log(b.filter(e => e > 6)); // []
```

【Python】[非破壊] filter(function, iterable)

```a = [1,2,3,4,5]
b = [2,3,4,5,6]
aItr = filter(lambda e: e < 6,  a)
bItr = filter(lambda e: e < 6,  b)
print(aItr) # <filter object at 0x00000159390AB6A0>
print(bItr) # <filter object at 0x00000159390AB710>
print(list(aItr)) # [1, 2, 3, 4, 5]
print(list(bItr)) # [2, 3, 4, 5]
```

【Python:numpy】[非破壊] numpy.where(condition[, x, y])

```a = np.array([1,2,3,4,5])
b = np.array([2,3,4,5,6])

# numpy.where(condition)
print(np.where(a < 6)) # (array([0, 1, 2, 3, 4], dtype=int64),)
print(a[np.where(a < 6)]) # [1 2 3 4 5]
print(np.where(b < 6)) # (array([0, 1, 2, 3], dtype=int64),)
print(a[np.where(b < 6)]) # [1 2 3 4]
```

【Python:numpy】[非破壊] indexing

```a = np.array([1,2,3,4,5])
b = np.array([2,3,4,5,6])

print([a < 6]) # [array([ True,  True,  True,  True,  True])]
print(a[[a < 6]]) # [1 2 3 4 5]
print([b < 6]) # [array([ True,  True,  True,  True, False])]
print(b[[b < 6]]) # [2 3 4 5]
```

## 配列内の要素が指定されたテスト関数を満たす場合、配列内の 値 を返します。そうでない場合は undefined を返します

• callback 関数が true を返す要素が見つかるまで、配列内の各要素に対して callback 関数を実行します。
• そのような要素が見つかると、find はすぐにその要素の値を返します。
• 配列内に見つからなければ、find は undefined を返します。
```const a = [1,2,3,4,5]
const b = [2,3,4,5,6]
console.log(a.find(e => e < 6)); // 1
console.log(b.find(e => e < 6)); // 2
console.log(b.find(e => e > 6)); // undefined
```

【Python】[非破壊] next(iterator[, default])

```a = [1,2,3,4,5]
b = [2,3,4,5,6]
print(next(filter(lambda e:e < 6, a), None)) # 1
print(next(filter(lambda e:e < 6, b), None)) # 2
print(next(filter(lambda e:e > 6, b), None)) # None
```

【Python:numpy】[非破壊] indexing

```a = np.array([1,2,3,4,5])
b = np.array([2,3,4,5,6])

print(a[a < 6][0]) # 1
print(b[b < 6][0]) # 2
print(b[b > 6][0]) # IndexError: index 0 is out of bounds for axis 0 with size 0
```

## 与えられた関数を、配列の各要素に対して一度ずつ実行します

【Js】[非破壊] Array.prototype.forEach()

```const b = ['〇', '×', '△']
b.forEach((val,idx) => console.log(`Index:[\${idx}] Value:[\${val}]`))
// Index:[0] Value:[〇]
// Index:[1] Value:[×]
// Index:[2] Value:[△]
```

【Python】[非破壊] for 文

```b = ['〇', '×', '△']
for (idx, val) in enumerate(b):
print('Index:[{}] Value:[{}]'.format(idx, val))
# Index:[0] Value:[〇]
# Index:[1] Value:[×]
# Index:[2] Value:[△]
```

【Python:numpy】[非破壊] numpy.ndenumerate(arr)

```b = np.array([['〇', '×', '△'], ['□', '★', '◇']])

for val in b:
print('そのまま Value:[{}]'.format(val))
# そのまま Value:[['〇' '×' '△']]
# そのまま Value:[['□' '★' '◇']]

for (idx, val) in np.ndenumerate(b):
print('ndenumerate Index:[{}] Value:[{}]'.format(idx, val))
# ndenumerate Index:[(0, 0)] Value:[〇]
# ndenumerate Index:[(0, 1)] Value:[×]
# ndenumerate Index:[(0, 2)] Value:[△]
# ndenumerate Index:[(1, 0)] Value:[□]
# ndenumerate Index:[(1, 1)] Value:[★]
# ndenumerate Index:[(1, 2)] Value:[◇]

for val in b.flat:
print('Flat Value:[{}]'.format(val))
# Flat Value:[〇]
# Flat Value:[×]
# Flat Value:[△]
# Flat Value:[□]
# Flat Value:[★]
# Flat Value:[◇]
```

## 引数に与えられた内容と同じ内容を持つ配列要素の内、最初のものの添字を返します

【Js】[非破壊] Array.prototype.indexOf()

• 存在しない場合は -1 を返します
```const b = [1,2,3,1,2,3]
console.log(b.indexOf(3)); // 2
console.log(b.indexOf(3, 2)); // 2
console.log(b.indexOf(3, 3)); // 5

let index = 0
let fromIndex = 0
do {
index = b.indexOf(1, fromIndex)
console.log(`IN WHILE index=\${index}`);
// IN WHILE index=0
// IN WHILE index=3
// IN WHILE index=-1
fromIndex = index + 1
} while(index >= 0)
console.log('done.'); // done.
```

【Python】[非破壊] list.index(x[, start[, end]])

```b = [1,2,3,1,2,3]
print(b.index(3)) # 2
print(b.index(3, 2)) # 2
print(b.index(3, 3)) # 5

index = 0
fromIndex = 0
while True:
try:
index = b.index(1, fromIndex)
print('IN WHILE index={}'.format(index))
# IN WHILE index=0
# IN WHILE index=3
fromIndex = index + 1
except Exception as e:
print('IN WHILE index={}'.format(e.args[0])) # 1 is not in list
break

print('done.') # done.
```

【Python:numpy】[非破壊] numpy.where(condition[, x, y])

```b = np.array([1,2,3,1,2,3])
print(np.where(b == 3)) # (array([2, 5], dtype=int64),)
print(np.where(b == 3)[0]) # [2 5]
print(np.where(b == 3)[0][0]) # 2
print(np.where(b == 3)[0][1]) # 5
```

## 配列のすべての要素を繋いで文字列にします

【Js】[非破壊] Array.prototype.join()

• undefined または null の要素は、空文字列に変換されます
```const a = [1, 2, 3]
const b = ['〇', '×', null, '△']
const c = ['〇', '×', '△']
console.log(a.join(',')) // 1,2,3
console.log(b.join(',')) // 〇,×,,△
console.log(c.join(',')) // 〇,×,△
```

【Python】[非破壊] str.join(iterable)

```a = [1, 2, 3]
b = ['〇', '×', None, '△']
c = ['〇', '×', '△']

print(','.join(a)) # TypeError: sequence item 0: expected str instance, int found
print(','.join(map(str, a))) # 1,2,3
print(','.join(b)) # TypeError: sequence item 2: expected str instance, NoneType found
print(','.join(map(str, b))) # 〇,×,None,△
print(','.join(c)) # 〇,×,△
```

【Python:numpy】[非破壊] numpy.array2string()

```a = np.array([1, 2, 3])
b = np.array(['〇', '×', None, '△'])
c = np.array(['〇', '×', '△'])

print(np.array2string(a)) # [1 2 3]
print(np.array2string(b)) # ['〇' '×' None '△']
print(np.array2string(c)) # ['〇' '×' '△']

print(np.array2string(a, separator=',')) # [1,2,3]
print(np.array2string(b, separator=',')) # ['〇','×',None,'△']
print(np.array2string(c, separator=',')) # ['〇','×','△']
```

## 与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列を生成します

【Js】[非破壊] Array.prototype.map()

```const a = [1, 2, 3]
console.log(a.map(e => e ** 2)); // [ 1, 4, 9 ]
console.log(a.map(e => {
return e ** 2
})); // [ 1, 4, 9 ]
console.log(a.map(e => {
e ** 2
})); // [ undefined, undefined, undefined ]
console.log(a.map((e, idx) => e * idx)); // [ 0, 2, 6 ]

const b = [{n: 'tanuki', v: 100}, {n: 'kitsune', v: 200}]
console.log(b.map(e => e.v * 1.08)); // [ 108, 216 ]
console.log(b.map(e => {
const copied = Object.assign({}, e)
copied.v *= 1.08;
return copied
})); // [ { n: 'tanuki', v: 108 }, { n: 'kitsune', v: 216 } ]
console.log(b); // [ { n: 'tanuki', v: 100 }, { n: 'kitsune', v: 200 } ]
```

【Python】[非破壊] map(function, iterable, ...)

```a = [1, 2, 3]
print(map(lambda e: e ** 2, a))  # <map object at 0x000001560E98F048>
print(list(map(lambda e: e ** 2, a)))  # [ 1, 4, 9 ]
print(list(map(lambda e: e[0] * e[1], enumerate(a))))  # [ 0, 2, 6 ]

b = [{'n': 'tanuki', 'v': 100}, {'n': 'kitsune', 'v': 200}]
print(list(map(lambda e: e['v'] * 1.08, b)))  # [108.0, 216.0]
print(list(map(lambda e: int(e['v'] * 1.08), b)))  # [ 108, 216 ]

def withTax(v):
vc = v.copy()
vc['v'] = int(vc['v'] * 1.08)
return vc

print(list(map(lambda e: withTax(e), b)))  # [{'n': 'tanuki', 'v': 108}, {'n': 'kitsune', 'v': 216}]
```

## 配列から最後の要素を取り除き、その要素を返します

【Js】[破壊的] Array.prototype.pop()

• 空の配列に対して pop() を実行した場合は、undefined を返します。
```const a = [1, 2, 3]
console.log(`POP:\${a.pop()} RESULT:\${a} LENGTH:\${a.length}`) // POP:3 RESULT:1,2 LENGTH:2
console.log(`POP:\${a.pop()} RESULT:\${a} LENGTH:\${a.length}`) // POP:2 RESULT:1 LENGTH:1
console.log(`POP:\${a.pop()} RESULT:\${a} LENGTH:\${a.length}`) // POP:1 RESULT: LENGTH:0
console.log(`POP:\${a.pop()} RESULT:\${a} LENGTH:\${a.length}`) // POP:undefined RESULT: LENGTH:0
```

【Python】[破壊的] list.pop([i])

```a = [1, 2, 3]

while(len(a) >= 0):
try:
print('POP:{} RESULT:{} LENGTH:{}'.format(a.pop(), a, len(a)))
# POP:3 RESULT:[1, 2] LENGTH:2
# POP:2 RESULT:[1] LENGTH:1
# POP:1 RESULT:[] LENGTH:0
except Exception as e:
print('Exception:{}'.format(e.args[0])) # Exception:pop from empty list
break

a = [1, 2, 3, 4, 5]
print('POP:{} RESULT:{} LENGTH:{}'.format(a.pop(1), a, len(a))) # POP:2 RESULT:[1, 3, 4, 5] LENGTH:4
b = [1, 2, 3, 4, 5]
print('POP:{} RESULT:{} LENGTH:{}'.format(b.pop(-1), b, len(b))) # POP:5 RESULT:[1, 2, 3, 4] LENGTH:4
```

## 配列の末尾に 1 つ以上の要素を追加することができます。

(「配列の連結」も参考にするとよい)

【Js】[破壊的] Array.prototype.push()

• 戻り値として新しい配列の要素数を返します。
```const a = [1, 2, 3]
const b = [4, 5]
const r = a.push(b)
console.log(a) // [ 1, 2, 3, [ 4, 5 ] ]
console.log(b) // [ 4, 5 ]
console.log(r) // 4

const a2 = [1, 2, 3]
const b2 = [4, 5]
const r2 = Array.prototype.push.apply(a2, b2)
console.log(a2) // [ 1, 2, 3, 4, 5 ]
console.log(b2) // [ 4, 5 ]
console.log(r2) // 5
```

【Python】[破壊的] list.append(x)

```a = [1, 2, 3]
b = [4, 5]
r = a.append(b)
print(a) # [1, 2, 3, [4, 5]]
print(b) # [4, 5]
print(r) # None
```

## アキュムレータと配列の各要素に対して（左から右へ）関数を適用し、単一の値にします。

• callback の最初の呼び出しのときに、最初の引数として使用されます。
• 設定しなかった場合、配列の最初の要素が使用されます。
• 空の配列を initialValue なしで実行するとエラーになります。
```const a = [1, 2, 3]
console.log(a.reduce((prev, cur, curIdx, arr) => cur + prev)) // 6

console.log(a.reduce((prev, cur, curIdx, arr) => {
console.log(`CurIndex:[\${curIdx}] Cur:[\${cur}] Prev:[\${prev}]`)
// CurIndex:[1] Cur:[2] Prev:[1]
// CurIndex:[2] Cur:[3] Prev:[3]
return cur + prev
})) // 6
console.log(a.reduce((prev, cur, curIdx, arr) => {
console.log(`CurIndex:[\${curIdx}] Cur:[\${cur}] Prev:[\${prev}]`)
// CurIndex:[0] Cur:[1] Prev:[0]
// CurIndex:[1] Cur:[2] Prev:[1]
// CurIndex:[2] Cur:[3] Prev:[3]
return cur + prev
}, 0)) // 6

const b = [{n:'a1', v:1}, {n:'a2', v:2}, {n:'a3', v:3}]
console.log(b.reduce((prev, cur) => cur + prev)) // [object Object][object Object][object Object]
console.log(b.reduce((prev, cur) => cur.v + prev)) // 32[object Object]
console.log(b.reduce((prev, cur) => cur.v + prev, 0)) // 6
```

【Python】[非破壊] functools.reduce(function, iterable[, initializer])

```from functools import reduce

a = [1, 2, 3]
print(reduce(lambda x, y: x + y, a))  # 6
print(sum(a))  # 6

b = [{'n': 'a1', 'v': 1}, {'n': 'a2', 'v': 2}, {'n': 'a3', 'v': 3}]
# print(reduce(lambda x, y: x + y, b))  # TypeError: unsupported operand type(s) for +: 'dict' and 'dict'
# print(reduce(lambda x, y: x['v'] + y, b)) # TypeError: unsupported operand type(s) for +: 'int' and 'dict'
print(reduce(lambda x,y: x + y['v'], b, 0)) # 6
print(reduce(lambda x,y: x['v'] + y['v'] if isinstance(x, dict) else x + y['v'], b)) # 6
```

## 配列の一部を取り出して新しい配列を返します

【Js】[非破壊] Array.prototype.slice(begin[,end])

```const a = [1, 2, 3, 4, 5]
console.log(a.slice(1)) // [ 2, 3, 4, 5 ]
console.log(a.slice(1, 2)) // [ 2 ]
console.log(a.slice(1, 3)) // [ 2, 3 ]
console.log(a.slice(1, -1)) // [ 2, 3, 4 ]
console.log(a.slice(1, -2)) // [ 2, 3 ]
console.log(a) // [ 1, 2, 3, 4, 5 ]
```

【Python】[非破壊] s[i:j:k])

• s の i から j まで、 k 毎のスライス
• -1は一番後ろの要素
```a = [1, 2, 3, 4, 5]
print(a[1:]) # [ 2, 3, 4, 5 ]
print(a[1: 2]) # [ 2 ]
print(a[1: 3]) # [ 2, 3 ]
print(a[1: -1]) # [ 2, 3, 4 ]
print(a[1: -2]) # [ 2, 3 ]
print(a) # [ 1, 2, 3, 4, 5 ]
# --
print(a[1::2]) # [2, 4]
print(a[::-1]) # [5, 4, 3, 2, 1]
print(a[::-2]) # [5, 3, 1]
```

## 配列の少なくとも 1 つの要素が、渡された関数によって実施されるテストに通るかどうかをテストします

【Js】[非破壊] boolean = some(callback[, thisArg])

```const a = [1, 2, 3, 4, 5]
console.log(a.some(e => e === 2)) // true
console.log(a.some(e => e === 10)) // false
console.log(a.some(e => e > 0)) // true
```

【Python】[非破壊] any(iterable)

```a = [1, 2, 3, 4, 5]
print(any(e == 2 for e in a)) # True
print(any(e == 10 for e in a)) # False
print(any(e > 0 for e in a)) # True
print(any(e is None for e in a)) # False
a.append(None)
print(any(e is None for e in a)) # True
```

## 配列の要素をソートします

【Js】[破壊的] sort(compareFunction)

```const a = [1, 2, 3, 4, 5]
let sorted = a.sort((e1, e2) => e2 - e1)
console.log(sorted) // [ 5, 4, 3, 2, 1 ]
console.log(a) // [ 5, 4, 3, 2, 1 ]

const b = [{'n': 'a1', 'v': 1}, {'n': 'a2', 'v': 2}, {'n': 'a3', 'v': 3}]
const copied = b.slice()
console.log(copied.sort((s1, s2) => s2.v - s1.v)) // [ { n: 'a3', v: 3 }, { n: 'a2', v: 2 }, { n: 'a1', v: 1 } ]
console.log(copied) // [ { n: 'a3', v: 3 }, { n: 'a2', v: 2 }, { n: 'a1', v: 1 } ]
console.log(b) // [ { n: 'a1', v: 1 }, { n: 'a2', v: 2 }, { n: 'a3', v: 3 } ]
```

【Python】[sorted():非破壊, list.sort():破壊的] sorted()

• list.sort() と sorted() には key パラメータがあります。
• これは比較を行う前にリストの各要素に対して呼び出される関数を指定するパラメータです。
• list.sort() と sorted() の両方とも reverse パラメータを 真偽値として受け付けます。
• このパラメータは降順ソートを行うかどうかの フラグとして利用されます
```a = [1, 2, 3, 4, 5]
b = [1, 2, 3, 4, 5]
print('sorted:{}, a:{}'.format(sorted(a, reverse=True), a)) # sorted:[5, 4, 3, 2, 1], a:[1, 2, 3, 4, 5]
print('Ret:{}, b:{}'.format(b.sort(reverse=True), b)) # Ret:None, b:[5, 4, 3, 2, 1]

c = [{'n': 'tanuki', 'v': 100}, {'n': 'kitsune', 'v': 200}]
d = [{'n': 'tanuki', 'v': 100}, {'n': 'kitsune', 'v': 200}]
print('sorted:{}, c:{}'.format(sorted(c, reverse=True, key=lambda e: e['v']), c))
# sorted:[{'n': 'kitsune', 'v': 200}, {'n': 'tanuki', 'v': 100}], c:[{'n': 'tanuki', 'v': 100}, {'n': 'kitsune', 'v': 200}]
print('Ret:{}, d:{}'.format(d.sort(reverse=True, key=lambda e: e['v']), d))
# Ret:None, d:[{'n': 'kitsune', 'v': 200}, {'n': 'tanuki', 'v': 100}]
```