Pythonで配列の要素を一括置換する

# はじめに

配列に含まれている特定の文字列を一括置換する方法の一つとして残しておきます。
多次元配列を扱っている場合においても、内包表記などを用いれば簡単に置換できるかなと思います。
今回は拡張子を一括で変更する場合を考えてみます。

**追記:**
@shiracamus さんよりnumpyの`char.replace`メソッドを教えていただきました。ありがとうございました。
今回は、コメントに記載していただいた[コード](https://qiita.com/takatea/items/45ed1ed6b1eb65e6576e#comment-b0d86f12aa1500aa1ed4)をそのまま引用させていただきます。

また、ファイル名にカンマが含まれていた場合に誤動作を起こしてしまうというご指摘もいただきました。numpyをもし使わない場合は、コメントにて記載してくださっている[内包表記のみを使った方法](https://qiita.com/takatea/items/45ed1ed6b1eb65e6576e#comment-fddd5f90b58bda3b4529)を使うのがベストかと思います。
ご指摘、ご教授ありがとうございました。


# 方法（numpy.char.replaceを使った方法）
前述の通り、@shiracamus さんのコードの引用となります。ありがとうございました。
nunpyのドキュメントを一応追加で記載してきます。（[numpy.char.replace](https://numpy.org/devdocs/reference/generated/numpy.char.replace.html#numpy-char-replace)）
numpyを使うならば、ご教授頂いた以下の`char.replace`メソッドを使うのが一番シンプルかつ簡単でベストだと思います。

```python
import numpy as np

orig_list = ["test1.png", "test2.png", "test3.png"]
print(np.char.replace(orig_list, "png", "jpg"))

orig_arr = [["test11.png", "test12.png", "test13.png"],
            ["test21.png", "test22.png", "test23.png"],
            ["test31.png", "test32.png", "test33.png"]]
print(np.char.replace(orig_arr, "png", "jpg"))

orig_arr_3d = [
    [["test111.png", "test112.png"],
     ["test121.png", "test122.png"],
     ["test131.png", "test132.png"]],
    [["test211.png", "test212.png"],
     ["test221.png", "test222.png"],
     ["test231.png", "test232.png"]],
    [["test311.png", "test312.png"],
     ["test321.png", "test322.png"],
     ["test331.png", "test332.png"]]
]
print(np.char.replace(orig_arr_3d, "png", "jpg"))
```



# 方法（joinを使った方法）
方法としてはリストを一度カンマ区切りの文字列に変換して、置換をします。
その後、置換された文字列を再度リストに戻すことで配列の一括変換を実現します。

**追記**
以下のコードでは、@shiracamus さんよりご指摘があった通り、ファイル名にカンマが入っていると誤動作を起こしてしまうという問題点があります。
そのため、@shiracamus さんよりご教授いただいた[内包表記のみを使った方法](https://qiita.com/takatea/items/45ed1ed6b1eb65e6576e#comment-fddd5f90b58bda3b4529)を使うのがベストかと思います。

以下は、議事録として一応残しておきたいと思います。


## 1次元のリストの場合
```python
orig_list = ["test1.png", "test2.png", "test3.png"]
# 一度joinで文字列に変換したのち、再度splitでリストに戻します。
replaced_list = ",".join(orig_list).replace("png", "jpg").split(",")
print(replaced_list) 
# ['test1.jpg', 'test2.jpg', 'test3.jpg']
```

## 2次元のリストの場合
```python
orig_arr = [["test11.png", "test12.png", "test13.png"],
            ["test21.png", "test22.png", "test23.png"], 
            ["test31.png", "test32.png", "test33.png"]]
# 内包表記で同様の処理を記述します
replaced_arr = [",".join(l).replace("png", "jpg").split(",") for l in orig_arr]
print(replaced_arr) 

# [['test11.jpg', 'test12.jpg', 'test13.jpg'], 
#  ['test21.jpg', 'test22.jpg', 'test23.jpg'], 
#  ['test31.jpg', 'test32.jpg', 'test33.jpg']]

```

## 関数として括りだす
置換する箇所を関数として括りだせばもっとシンプルになります。
また、次元数を簡単に取得するためにnumpyを使うことでn次元の配列にも容易に対応できます。
（そんな高次元で使うことはないと思うのですが、一応残しておきます）

それでは、[組み込み関数のreplace](https://docs.python.org/ja/3/library/stdtypes.html?highlight=str%20replace#str.replace)をラッピングするような形で関数を定義して書き直してみます。


```python
import numpy as np

# Ref. built-in::str.replace(old, new[, count])
def replace_for_arr(data: np.ndarray, old, new):
     
     '''2次元以上のリストのときは再帰します'''
     if len(data.shape) >= 2:
         return [replace_for_arr(d, old, new) for d in data]

     return ",".join(data).replace(old, new).split(',')

# ===== <1次元の場合> =====
orig_list = ["test1.png", "test2.png", "test3.png"]
print(replace_for_arr(np.asarray(orig_list), "png", "jpg")) 
# ['test1.jpg', 'test2.jpg', 'test3.jpg']

# ===== <2次元の場合> =====
orig_arr = [["test11.png", "test12.png", "test13.png"],
            ["test21.png", "test22.png", "test23.png"], 
            ["test31.png", "test32.png", "test33.png"]]
print(replace_for_arr(np.asarray(orig_arr), "png", "jpg")) 
# [['test11.jpg', 'test12.jpg', 'test13.jpg'], 
#  ['test21.jpg', 'test22.jpg', 'test23.jpg'], 
#  ['test31.jpg', 'test32.jpg', 'test33.jpg']]

# ===== <3次元の場合> =====
orig_arr_3d = [
    [["test111.png", "test112.png"], 
     ["test121.png", "test122.png"], 
     ["test131.png", "test132.png"]],
    [["test211.png", "test212.png"], 
     ["test221.png", "test222.png"], 
     ["test231.png", "test232.png"]],
    [["test311.png", "test312.png"], 
     ["test321.png", "test322.png"], 
     ["test331.png", "test332.png"]]
]

print(replace_for_arr(np.asarray(orig_arr_3d), 'png', 'jpg'))
# [[['test111.jpg', 'test112.jpg'],
#   ['test121.jpg', 'test122.jpg'],
#   ['test131.jpg', 'test132.jpg']],
#  [['test211.jpg', 'test212.jpg'],
#   ['test221.jpg', 'test222.jpg'],
#   ['test231.jpg', 'test232.jpg']],
#  [['test311.jpg', 'test312.jpg'],
#   ['test321.jpg', 'test322.jpg'],
#   ['test331.jpg', 'test332.jpg']]]

```