【学問のすすめ】中世ヨーロッパ写字生のように黙って静かに手を動かすブログ

これまで習ったことや学んだことを記事にまとめています。ITネタが多いです。

【Python】リスト内の隣り合った数が同じだった場合に片方を削除するコード「remove_adjacent.py」を書いてみた(ソースコードあり)

f:id:pesia_one:20180902234258j:plain:w400

Python3で受け取ったリスト内の隣り合った数が同じだった場合、その片方を削除したリストを生成するコードを書いてみました。
開始時点で下記のコードが与えられており、2行目の「# ここになにがしかのコードを入力する」をどうするかを考えます

def remove_adjacent(li):
# ここに何がしかのコードを入力する
            
print(remove_adjacent([1,2,2,3]))    
print(remove_adjacent([2,2,3,3,3])) 
print(remove_adjacent([]))

 

はじめに

コードの要件

今回作成するコードの要件は下記の通りです。

  • 要件1:remove_adjacent関数を記述する
  • 要件2:リストを受け取り隣接した要素が同じだった場合にその要素を削除する
  • 要件3:処理の後に値を返却する

入力値と出力値

入力される値は下記の通りです。

  • 入力1:[1,2,2,3]
  • 入力2:[2,2,3,3,3]))
  • 入力3:[]

出力を予定している値は下記の通りです。

  • 出力1:[1,2,3]
  • 出力2:[2,3]
  • 出力3:[ ]

コード書いてみた

正解のコード

正解のコードは下記です。(Python3.2.5で動作を確認)

#!/usr/bin/env python3
# -*- coding; utf-8 -*-

def remove_adjacent(li):
    if len(li) != 0:
        n1  = []
        n1.append(li[0])
        for i in range(1, len(li)):
            if li[i] != li[i - 1]:
                n1.append(li[i])
            return n1
    else:
        return li
            
print(remove_adjacent([1,2,2,3]))    
print(remove_adjacent([2,2,3,3,3])) 
print(remove_adjacent([]))

下記URLのGitHubリポジトリにも同じコードを掲載しています

https://github.com/a1852rw/aiit_001_system_programing/blob/master/lesson_003/006_remove_adjacent.py

  • リポジトリ名:aiit_001_system_programing
  • ファイル名:006_remove_adjacent.py
  • 保存先ディレクトリ:aiit_system_programing/lesson_003

 

解説

コードの内容を説明します。

#!/usr/bin/env python3
# -*- coding; utf-8 -*-

shebang(シバン)と文字コードの指定です。
このコードがPython3で動作すること、文字の出力はUTF-8で行われることを示しています。(ここで文字コードを指定しないと日本語が文字化けします)

def remove_adjacent(li):

最初の行で関数「remove_adjacent」に仮引数「li」を設定しています。

   if len(li) != 0:
# ここのコードは後で解説
    
    else:
        return li

仮引数「li」が「0」でない場合 ( = リストの中になにがしかの数値が入力されている場合)はそれ以下の行にある処理に進みます
それ以外の場合( = リストに何も入力されていない場合)は入力された文字列をそのまま返却します。

       n1  = []
        n1.append(li[0])

変数「n1」に中身が空のリストを挿入する。これにより変数「n1」をリストとして扱うことができるようになります。
さらに「.append(li[0])」でリストliのインディックス番号0の値( = リストの最初に格納されている要素)を変数「n1」のリストに追加します。
これを記述しないと変数にリストの要素を追加できない、リストの最初の要素が削除された値が出力される、などの問題が発生します

       for i in range(1, len(li)):
            if li[i] != li[i - 1]:
                n1.append(li[i])
            return n1

「for i in range(1, len(li)):」で繰り返しの回数を1〜リスト「li」の要素数 に指定します。 if文ではリスト「li」の要素i番目の値が i-1 番目と一致しない場合にリスト「li」のi番目の要素をリスト「n1」に追加します。 これをfor文で繰り返すことにより隣り合う要素と一致しない要素だけがリストに追加され、結果として「要件2」を満たすリストが作成されます

 

あとがき

これは難しかったです。特に「要件2」で「隣接した要素が一致した場合に片方を削除して」とされていたところで迷いました。
結局ネット上で見つけたコードを参考に正解を導くことになりました。

結論:10分考えてわからなければ正解を探した方がいい

知らないことを考えても答えは見つかりませんでした(結構な時間かけましたが本当にわかりませんでした)。調べるなり誰かに教えてもらうなりして正解を眺めながら正解の理由を考えたほうがはるかに効率的です。