アイソモカ

知の遊牧民の開発記録

開発記録 200211 Tue (100本ノック #061, #062, #063, LevelDB)

前回 に続き、Key-Value-Store (KVS) として LevelDB を使っていきます。前回 LevelDB チュートリアルを少し書いたので、今回はとてもスムーズにできました。

言語処理100本ノック #061: KVSの検索

61. KVSの検索

60で構築したデータベースを用い,特定の(指定された)アーティストの活動場所を取得せよ.

解答

# knock_061.py
import sys
import plyvel
name_area_db = plyvel.DB('artist_name_area.lbd')

if __name__ == '__main__':
    artist = sys.argv[1]
    if name_area_db.get(artist.encode('utf-8')):
        print(name_area_db.get(artist.encode('utf-8')).decode('utf-8'))
    else:
        print(artist, 'is not in the database')

 ↓実行

$ python knock_061.py きゃりーぱみゅぱみゅ
Japan

$ python knock_061.py ぴーじぇい
ぴーじぇい is not in the database

コマンドライン引数に空白を含める場合は、クォーテーションマークで囲えばよい。

$ python knock_061.py 'Sum 41'
Canada

 

言語処理100本ノック #062: KVS内の反復処理

62. KVS内の反復処理

60で構築したデータベースを用い,活動場所が「Japan」となっているアーティスト数を求めよ.

解答

# knock_062.py
import plyvel
name_area_db = plyvel.DB('artist_name_area.lbd')

if __name__ == '__main__':
    artist_list = []
    for key, value in name_area_db:
        if value == 'Japan'.encode('utf-8'):
            artist_list.append(key.decode('utf-8'))
    print(len(artist_list))

 ↓実行

$ python knock_062.py
22128

 

言語処理100本ノック #063: オブジェクトを値に格納したKVS

63. オブジェクトを値に格納したKVS

KVSを用い,アーティスト名(name)からタグと被タグ数(タグ付けされた回数)のリストを検索するためのデータベースを構築せよ.さらに,ここで構築したデータベースを用い,アーティスト名からタグと被タグ数を検索せよ.

解答

JSONから取得するタグは辞書形式なので、'value' をリストに格納し、リストを pickle 形式でLevelDB データベースに登録した。 タグの 'count' が1以上の場合は、その数分だけタグをリストに格納する。 タグがないアーティストもいたので、その場合はリストを空にした。

プログラムは、コマンドライン引数なしで実行すると、データベースを構築する。 コマンドライン引数にアーティスト名を置いて実行すると、アーティスト名からデータベースを検索する。

# knock_063.py
import sys
import gzip
import json
DATAFILE = './artist.json.gz'
import plyvel
DATABASE = 'artist_name_tags.lbd'
name_tags_db = plyvel.DB(DATABASE, create_if_missing=True)
import pickle

def read_json(file):
    with gzip.open(file, 'rt') as datafile:
        for l in datafile:
            data_json = json.loads(l)
            if 'tags' in data_json:
                yield (data_json['name'], data_json.get('tags'))
            else:
                yield (data_json['name'], [])


def make_name_tags_db(file):
    for key, value in name_tags_db:
        name_tags_db.delete(key)

    for artist in list(read_json(file)):
        tag_list = []
        for tag_dict in artist[1]:
            for c in range(tag_dict['count']):
                tag_list.append(tag_dict['value'])
        p_tag_list = pickle.dumps(tag_list)
        name_tags_db.put(artist[0].encode('utf-8'), p_tag_list)


if __name__ == '__main__':
    if len(sys.argv) > 1:
        artist = sys.argv[1]
        if name_tags_db.get(artist.encode('utf-8')):
            tags = pickle.loads(name_tags_db.get(artist.encode('utf-8')))
            print('tag count:', len(tags), '\ntags:', tags)
        else:
            print(artist, 'is not in the database')
    else:
        make_name_tags_db(DATAFILE)

 ↓実行

$ python knock_063.py Avicii
tag count: 4 
tags: ['progressive house', 'house', 'seen live', 'edm']

$ python knock_063.py 'the HIATUS'
tag count: 0 
tags: []

$ python knock_063.py ぴーじぇい
ぴーじぇい is not in the database