第116回【Python】構造体の整列、構造体の更新
現在取り組んでいるのは、paiza ラーニング問題集「クラス・構造体メニュー」になります。
はじめに
猫とキャンプと野球観戦と AWS が大好きな旦那、LeoSaki です。モフモフしたい。
Python をゼロから勉強してみよう、のコーナー 116 回目です。
面接も担当しています。コミュ障の人見知りなので、いつも準備を完璧にしてから臨みます。さて、「この業界、ずーっと勉強勉強が必要になりますが大丈夫ですか?」と必ず聞くようにしています。もちろん、面接に来ているわけで、ほとんどの方から「もちろんです」「大丈夫です」という回答が戻ってきます。過去に 1 度だけ、「勉強は嫌いなのでしたくありません」と答えた人がいました。丁重にお断りしました。
それでは、今日も頑張ってみようと思います。
構造体の整列
クラスの学級委員である paiza 君は、クラスのみんなに次のような形式でアカウントの情報を送ってもらうよう依頼しました。
名前 年齢 誕生日 出身地
送ってもらったデータを使いやすいように整理したいと思った paiza 君はクラス全員分のデータを次の形式でまとめることにしました。
User{
nickname : 名前
old : 年齢
birth : 誕生日
state : 出身地
}
この情報を扱いやすくするために、年齢が昇順になるようにデータを並び替えることにしました。
クラスメートの情報が与えられるので、並び替えた後のデータを出力してください。
N
n_1 o_1 b_1 s_1
...
n_N o_N b_N s_N
・ 1 行目では、paiza君のクラスの人数 N が与えられます。
・ 続く N 行のうち i 行目 (1 ≦ i ≦ N) では、 i 番の生徒の名前・年齢・誕生日・出身地を表す整数・文字列 n_i ,o_i ,b_i , s_i が順に半角スペース区切りで与えられます。
すべてのテストケースにおいて、以下の条件をみたします。
・ 1 ≦ N ≦ 10
・ n_i , b_i (1 ≦ i ≦ N) は 1 文字以上 20 文字以下の文字列
・ b_i (1 ≦ i ≦ N) はMM/DD 形式の文字列(例 1月2日 → 01/02 12月31日 → 12/31)
・ 1 ≦ o_i ≦ 100
・ o_i (1 ≦ i ≦ N) は重複することがないことが保証されている。
入力例
3
mako 13 08/08 nara
taisei 16 12/04 nagano
megumi 14 11/02 saitama
出力例
mako 13 08/08 nara
megumi 14 11/02 saitama
taisei 16 12/04 nagano
Python の便利さを実感できる問題。sort 一発で並び替えられてしまう。
Python
class Student:
def __init__(self,nickname,old,birth,state):
self.nickname = nickname
self.old = old
self.birth = birth
self.state = state
N = int(input())
students = [None] * N
for i in range(N):
n,o,b,s = map(str,input().split())
students[i] = Student(n,o,b,s)
sort_students = sorted(students,key=lambda x:x.old)
for student in sort_students:
print(student.nickname,student.old,student.birth,student.state)
VBA
Type Students
name As String
old As Integer
birth As String
state As String
End Type
Sub class_primer__sort()
N = Cells(1, 1)
Dim mem() As Students
ReDim mem(N - 1)
For i = 0 To N - 1
S = Split(Cells(i + 2, 1), " ")
mem(i).name = S(0)
mem(i).old = Val(S(1))
mem(i).birth = S(2)
mem(i).state = S(3)
Next
Dim temp As Students
For i = LBound(mem) To UBound(mem)
For j = i + 1 To UBound(mem)
If mem(i).old > mem(j).old Then
temp = mem(i)
mem(i) = mem(j)
mem(j) = temp
End If
Next
Next
For i = LBound(mem) To UBound(mem)
Debug.Print mem(i).name & " " & mem(i).old & " " & mem(i).birth & " " & mem(i).state
Next
End Sub
構造体の更新
クラスの学級委員である paiza 君は、クラスのみんなに次のような形式でアカウントの情報を送ってもらうよう依頼しました。
名前 年齢 誕生日 出身地
送ってもらったデータを使いやすいように整理したいと思った paiza 君はクラス全員分のデータを次の形式でまとめることにしました。
User{
nickname : 名前
old : 年齢
birth : 誕生日
state : 出身地
}
途中で名前が変わった際にいちいちデータを修正するのが面倒だと思ったあなたは、生徒の構造体と新しい名前を受け取り、その名前を修正する関数 changeName
を作成し、それを用いて生徒の名前を更新することにしました。
クラスの人数と全員の情報、更新についての情報が与えられるので、入力に従って名前を更新した後のクラスのメンバーの情報を出力してください。
N K
n_1 o_1 b_1 s_1
...
n_N o_N b_N s_N
a_1 nn_1
...
a_K nn_K
・ 1 行目では、paiza君のクラスの人数 N と名前更新の回数 K が与えられます。
・ 続く N 行のうち i 行目 (1 ≦ i ≦ N) では、 i 番の生徒の名前・年齢・誕生日・出身地を表す整数・文字列 n_i ,o_i ,b_i , s_i が順に半角スペース区切りで与えられます。
・ 続く K 行では、名前を更新する生徒の番号 a_i と、その人の新しい名前 nn_i が空白区切りで与えられます。
すべてのテストケースにおいて、以下の条件をみたします。
・ 1 ≦ N , K ≦ 10
・ n_i , b_i , nn_i (1 ≦ i ≦ N) は 1 文字以上 20 文字以下の文字列
・ b_i (1 ≦ i ≦ N) はMM/DD 形式の文字列(例 1月2日 → 01/02 12月31日 → 12/31)
・ 1 ≦ o_i ≦ 100
・ 1 ≦ a_i ≦ N (1 ≦ i ≦ K)
入力例
3 2
mako 13 08/08 nara
taisei 16 12/04 nagano
megumi 14 11/02 saitama
2 taihei
3 megu
出力例
mako 13 08/08 nara
taihei 16 12/04 nagano
megu 14 11/02 saitama
名前がころころ変わっちゃったら大変だと思うけど。paiza 君のクラスはすげーな。
Python
class Student:
def __init__(self,nickname,old,birth,state):
self.nickname = nickname
self.old = old
self.birth = birth
self.state = state
def changeName(self,nickname):
self.nickname = nickname
N,K = map(int,input().split())
students = [None] * N
for i in range(N):
n,o,b,s = map(str,input().split())
students[i] = Student(n,o,b,s)
for i in range(K):
a,n = input().split()
a = int(a) - 1
students[a].changeName(n)
for s in students:
print(s.nickname,s.old,s.birth,s.state)
VBA
### class_primer__change
Private mem As Students
Private Type Students
name As String
old As Integer
birth As String
state As String
End Type
Property Get mem_name()
mem_name = mem.name
End Property
Property Get mem_old()
mem_old = mem.old
End Property
Property Get mem_birth()
mem_birth = mem.birth
End Property
Property Get mem_state()
mem_state = mem.state
End Property
Property Let members(S)
mem.name = S(0)
mem.old = Val(S(1))
mem.birth = S(2)
mem.state = S(3)
End Property
Sub changeName(new_name)
mem.name = new_name
End Sub
### 標準モジュール
Public Sub class_primer__change()
NK = Split(Cells(1, 1), " ")
N = Val(NK(0))
K = Val(NK(1))
Dim cls() As New class_primer__change
ReDim cls(N - 1)
For i = LBound(cls) To UBound(cls)
S = Split(Cells(i + 2, 1), " ")
cls(i).members = S
Next
For i = 1 To K
S = Split(Cells(i + N + 1, 1), " ")
num = Val(S(0)) - 1
new_name = S(1)
cls(num).changeName (new_name)
Next
For i = LBound(cls) To UBound(cls)
Debug.Print cls(i).mem_name & " " & cls(i).mem_old & " " & cls(i).mem_birth & " " & cls(i).mem_state
Next
End Sub
最後に
Python の簡潔なこと。そして、VBA が VBA らしくなってきました。多分、綺麗に書けているわけではないですが、VBA でも同じようなことができるのか、と驚く人が少しでもいれば幸いでございます。
クラスや構造体は見た目がコードっぽいので好きです。なんとなく。まぁ、使いこなせば、かなり便利なものなので、しっかり勉強して使いこなせるようになりたいものです。しかし、VBA で書くのが辛くなってきた・・・。
引き続き、よろしくお願いいたします!
ディスカッション
コメント一覧
まだ、コメントがありません