質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.10%

python ランキング 書き込み

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,090

score 18

以前作っていただいたコードを書き直してランク付けした上で他のtxtファイルに移す作業のコードを教えていただきたいです。

https://teratail.com/questions/96246
前回質問し、教えていただいた内容です。コードも教えていただきました。

with open('file1.txt') as f:
    value_list = [line.rstrip() for line in f]

with open('file2.txt') as f:
    key_list = [line.rstrip() for line in f]
data_dict = {}
for raw_value in value_list:
    key, value = raw_value.split(';')
    if key in data_dict:
        data_dict[key].append(value)
    else:
        data_dict[key] = [value]

for key, values in sorted(data_dict.items(), key=lambda x: -len(x[1])):
    for value in values:
        print(key + ';' + value)

    if len(values) == 0:
        pass
    else:
        print(len(values))


以上です。表記の仕方がわかりにくかったらおっしゃってください。
今、ファイル1にはソートされた下記のようなデータが100万近くあります。
1234567;7890984
1234567;8764589
1234567;9275785
1345678;9868465
2345678;8979894
2345678;9078990
またファイル2にはソートされた下記のようなデータが30万近くあります。
1234567
1345678
2347889

結果としては、
ファイル1の;より左の数値とファイル2が合致した時のみを考え、合致した場合はファイル1にその数字を含む行がいくつあるのかを数え上位からランク付けします。
例としては、以下のようです。
1234567;7890984
1234567;8764589
1234567;9275785
3
1345678;9868465
1

このように解決、編集していただきました。そのコードに手を加えさせていただき、新しくコードを書きました。(このコードの結果を別のファイルへ保存する方法しようと思い書きました。)
新しく、ファイルを作りそこに上記の結果を保存したいです。
下記のようなコードを書きましたが、最後のf3.write(str1)のところで通りません。(f3.writeは2回しようしてはいけないなどの決まりがありますか?)初心者なので、ヘンテコな編集になっているかもしれません。ご指摘よろしくお願いします。

with open('ファイル1.txt') as f:
    value_list = [line.rstrip() for line in f]

with open('ファイル2.txt') as f:
    key_list = [line.rstrip() for line in f]

f3 = open('ファイル3.txt', 'w')

data_dict = {}
for raw_value in value_list:
    key, value = raw_value.split(';')
    if key in data_dict:
        data_dict[key].append(value)
    else:
        data_dict[key] = [value]

for key, values in sorted(data_dict.items(), key=lambda x: -len(x[1])):
    for value in values:
        print(key + ';' + value)
        f3.write(key + ';' + value + '\n')

    if len(values) == 0:
        pass
    else:
        print(len(values))
        str1 = len(values)
        f3.write(str1)
f.close()
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

# 実際にはファイルから読み込む
value_list = ['1234567;7890984', '1234567;8764589', '1234567;9275785', '1345678;9868465', '2345678;8979894', '2345678;9078990']
key_list = ['1234567', '1345678', '2347889']

data_dict = {}
for raw_value in value_list:
    key, value = raw_value.split(';')
    if key in data_dict:
        data_dict[key].append(value)
    else:
        data_dict[key] = [value]

for key, values in sorted(data_dict.items(), key=lambda x: -len(x[1])):
    # for value in values:
    #     print(key + ';' + value)

    if len(values) == 0:
        pass
    else:
        print(key + ';' + values[0])
        print(len(values))

"""実行結果(修正前)
1234567;7890984
1234567;8764589
1234567;9275785
3
2345678;8979894
2345678;9078990
2
1345678;9868465
1
"""

"""実行結果(修正後)
1234567;7890984
3
2345678;8979894
2
1345678;9868465
1
"""

前回書いたのは書き捨てのプログラムだったため、変更が必要でした。
どんどん仕様が増えていくと、コーディングの見通しが立ちません。
出来るだけ序盤に『何が出来る必要があるのか』を明確にするようにしてください。

下記のようなデータが100万近くあります。

このスクリプトがエラーなく動けばいいですが、ちょっと自信がないです。
大きなデータに対応させるためには、工夫が必要かもしれません。

その要素の最初の一つとそれについての要素数を書き出したいです。

修正しました。


また、別に著作権云々大騒ぎする気はありませんが...
質問で他人が書いたプログラムを引用する場合、それを明示した方がよいです。
前回質問へのリンクを貼り、更に引用符を付けるとよいでしょう。

**リンクの貼り方**
[リンク先の呼称](URL)

**引用符の付け方**
> 引用したい文
> 引用したい文

リンクを貼ると、このようになります。

引用符をつけると、このようになります。

コードも引用できます。

追記を受けて

最後のf3.write(str1)のところで通りません。
TypeError: expected a character buffer object

エラーが再現出来ていないのですが、おそらく数値を渡しているのが原因です。
文字列にキャストしてあげてください。

str1 = len(values)
f3.write(str(str1))

ついでに、最後closeするものを間違えています。

f.close()

明示的に閉じる必要があるのはfではなくf3では。

さらに、コメントを受けて

1回目は (中略) TypeError:cannot concatenate 'str' and 'int' objects

エラーメッセージこそ異なりますが、こういうことです。

>>> 'hoge' + 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be str, not int
>>> 'hoge' + str(1)
'hoge1'

あとは、質問者様ご自身がどのような工夫をしたのか見えるといいですね。
今の状態では、ただ投げ出しているのか、壁にぶつかっているのかわからないです。
人の書いたコードはよく読んで内容を把握し、そしてアレンジする技術を持ちましょう。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/16 16:33

    コード見ていなかったです。ありがとうございます。実行できました!
    for文から抜け出して書いたからこのように出力出来た、という解釈であってますか?

    キャンセル

  • 2017/10/16 16:36

    for value in values:のブロックはlen(values)回だけ繰り返しますからね。

    キャンセル

  • 2017/10/16 16:39

    なるほど。ありがとうございます!
    助かりました。もう一度このコードを1行ずつ理解しながら書き写して実行してみようと思います。ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.10%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る