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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

4回答

362閲覧

Python3  データ収集 特定リストの要素の集計

python3_beginer

総合スコア46

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2018/04/08 12:49

編集2018/04/08 13:59

目標)
会社の中で、男女混合フットサルのグループをつくりたい。
ただし、一定のレベル以上のメンバーの特選グループをつくりたい
そのため、体力テスト5科目を実施し、特選グループに入れるメンバーの数を数えたい。

特選グループ条件
男女共通: 体力テスト5科目の合計点が300点以上

更に、男女それぞれもう一つ追加条件を加える。

女性(f): 100m走、200m走 の合計スコアが160点以上
男性(m): 300m走、400m走 の合計スコアが160点以上

例) 全体が2人の場合 (N=2)

性別 50m走 100m走 200m走 300m走 400m走
f 70 78 82 57 74
m 68 81 81 60 78

記入例) 会社にいる N = 5人から特選グループをつくる。


f 70 78 82 57 74
m 68 81 81 60 78
f 63 76 55 80 75
f 90 100 96 10 10
m 88 78 81 97 93

問題)

以下のコードで期待値通りの出力を取得
然しながら、filite, lambdaを利用してスマートなコードに書きなおしたい。

count = 0 以下からのコードを書きなおしたい。
アドバイス宜しくお願い致します。

コード members = int(input()) data = [ [str(e) for e in input().split()] for _ in range(members) ] count = 0 for i in range(members): sum = int(data[i][1]) + int(data[i][2]) + int(data[i][3]) + int(data[i][4]) + int(data[i][5]) s_sum = int(data[i][2]) + int(data[i][3]) l_sum = int(data[i][4]) + int(data[i][5]) if data[i][0] == "s": if (sum >= 360) and (s_sum >= 160): count += 1 else: pass else: if (sum >= 360) and (l_sum >= 160): count += 1 else: pass print(count)

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

データ変換を行います
data = [(x[0],list(map(int,x[1:]))) for x in data]

とりあえず合計が360以上を抽出する
cond1 = list(map(lambda x:sum(x[1])>=360,data))

男女の指標、160以上を抽出する
cond2 = list(map(lambda x:(sum(x[1][1:3]) if x[0][0]=='f' else sum(x[1][3:]))>=160, data))

両方とも達成した人の合計
sum(map(int, [x and y for x,y in zip(cond1,cond2)]))

投稿2018/04/08 14:09

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LouiS0616

2018/04/08 14:20

条件を分けて考えればよかったんですね。私は難しく考えすぎていたようです。
python3_beginer

2018/04/08 15:03

お返事頂きありがとうございます。 条件分岐の際、全体→男性、全体→女性と考えてしまい、lambda()をうまく利用できませんでした。 上記のように、全体→男性、女性とまとめて考えればよかったんですね。 発想の視点、lambda()の利用方法とても有益な情報でした。 ありがとうございました。
退会済みユーザー

退会済みユーザー

2018/04/08 15:11

コメントありがとうございます。 ループより、一旦全対象に当てて計算した方が速いです。うまく説明できず、すみませんでした。
guest

0

ベストアンサー

map, filterなどを意識した場合、以下のようにするとスマートかもしれません。
ポイントとしては、issuperiority(特選のスコアであるか?)をmapで体力テストデータに対して処理を行い、その結果をsumすることで特選メンバーをカウントします。

python

1test_records = [ 2 # f/m 50m 100m 200m 300m 400m 3 input().split() 4 for _ in range(int(input())) # N 5] 6 7 8def issuperiority(record): 9 gender, data = record[0], list(map(int, record[1:])) 10 common = sum(data) >= 360 11 another = sum([data[1:3], data[3:5]][gender == 'm']) >= 160 12 return common and another 13 14print(sum(map(issuperiority, test_records)))

投稿2018/04/08 14:38

arch_

総合スコア158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

python3_beginer

2018/04/09 01:14 編集

お返事頂きありがとうございます。 ポイント整理、コードの詳細、ありがとうございます。 単純なループ処理ではなく、発想を変えればこんなにスマートになるのかと感動しました。 勉強不足で申し訳ないのですが、追記で質問よろしいでしょうか。 issuperiority関数のラストからの2行目です。 another = sum([data[1:3], data[3:5]][gender == 'm']) >= 160 2つ質問がございます。それぞれ以下の解釈で合っているでしょうか? まず、sum()関数の中にあるリスト二つについて。 sum()の中に、リストを二つ入れることで条件分岐の役割を果たす。 次に、sum()関数の条件分岐について 前半: [data[1:3], data[3:5]] 全体の100m,200m走が160点以上 かつ300m,400m走が160点以上のリスト →男女問わずスコアの一致のみ 後半: [gender == 'm'] スコアクリアした男女混合の中から、男性のみ絞る 二つの条件を合わせると、男性のみの抽出になってしまうのではないかと混乱しております。 重ね重ね申し訳ありません。お時間があればご教授お願い致します。
arch_

2018/04/09 02:51

anotherの処理は少し特殊になっていますが、紐解くと便利なものだと理解できると思います。 sum内部の処理と同じ内容になる書き方をすると、 data[3:5] if gender == 'm' else data[1:3] すなわち、条件分岐は gender == 'm' で成り立っていることになります。 では、なぜ [data[1:3], data[3:5]][gender == 'm'] の書き方で上手く動いているのかですが、この処理は大きく見ると、 [リスト本体][リストへのアクセス] で成り立っています。 「リストへのアクセス」gender == 'm' の処理は、genderが 'm'(男性)の場合はTrueを、'f'(女性)の場合はFalseと判定します。また、bool(True/False)はint(整数型)のサブクラス(>>> issubclass(bool, int) # True)にあたるので、リストの要素へのアクセスに用いることができます(False → 0, True → 1)。 これらをまとめると、 [data[1:3], data[3:5]][gender == 'm'] この処理は、m/fのパターンで [data[1:3], data[3:5]][False] # f [data[1:3], data[3:5]][True] # m boolはintの役割を果たすので、 [data[1:3], data[3:5]][0] # f [data[1:3], data[3:5]][1] # m よって、 data[1:3] # f: 100m, 200mのスコア data[3:5] # m: 300m, 400mのスコア という結果がanotherのsumの内部で得られます。よって、f/mのスコアの合計を最後にsum >= 160で判定することで、女性or男性の別スコアが160点以上であるか評価しています。
python3_beginer

2018/04/09 02:58

お返事頂きありがとうございます。 詳しい説明ありがとうございます。 [リスト本体][リストへのアクセス], リストの要素へのアクセスに用いることができます(False → 0, True → 1)の内容を理解できていませんでした。 新しい知識ばかりでしたが、とても丁寧な説明で初心者の私でも理解することができました。 いつも助けて頂きありがとうございます。
guest

0

ちょっと微妙ですが、せっかく書いたので晒します。参考までに。

Python

1n = int(input()) 2 3data = [ 4 input().split() for _ in range(n) 5] 6 7count = 0 8for datum in data: 9 sex, *record = datum 10 record = [int(e) for e in record] 11 12 if sum(record) < 300: 13 continue 14 15 count += { 16 'm': lambda r: r[3] + r[4] >= 150, 17 'f': lambda r: r[0] + r[1] >= 150 18 }[sex](record) 19 20print(count)

Wandbox

実は

これを書く以前に『オレ流』で二本書いたんですが、どちらも冗長になってしまいました。

  • 関数を濫用した割に美しくないコード Wandbox
  • クラスを濫用した割に分かりづらいコード Wandbox

シンプル・イズ・ベストってことですね。

投稿2018/04/08 14:02

LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

python3_beginer

2018/04/08 15:05

お返事頂きありがとうございます。 3つもサンプルコードを提示して頂きとても勉強になります。 乏しい発想力なので、サンプルコードを復習し柔軟な視点をもてるよう鍛えていきます。 たくさんのコードが見れてとても楽しかったです。 ありがとうございました。
guest

0

スマートに、ということなのと、内包表記での回答がなかったので内包表記で書いてみました。内包表記はmap, filterと等価のことができ、記述量、パフォーマンス(速度)で若干有利です。
ロジックはFrank_Sheさんの回答と同じです(ミスがなければ)。入力周りは変えてあります。

python

1string = """f 70 78 82 57 74 2m 68 81 81 60 78 3f 63 76 55 80 75 4f 90 100 96 10 10 5m 88 78 81 97 93""" 6 7data = [(lambda line: [line[0]] + [int(x) for x in line[1:]])(line.split()) 8 for line in string.split("\n")] 9 10print(len([line for line in data # 本当は一行で書けるが、改行・インデントしないと読めない 11 if ((sum(line[1:]) >= 300) and 12 ((sum(line[1:3]) >= 160) 13 if line[0] == "f" else 14 (sum(line[3:5]) >= 160)))]))

投稿2018/04/09 02:52

hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

python3_beginer

2018/04/09 04:43

お返事頂きありがとうございます。 既に解決済にも関わらず、足りていない情報を共有して頂きありがとうございます。 希望通りのスマートな表記で見ていてとても気持ちがいいです。 復習して、内包表記、map,filiter等使いこなしたいです。 ご指導ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問