第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 で書くのが辛くなってきた・・・。

引き続き、よろしくお願いいたします!

Pythonpaiza,学習,Python

Posted by LeoSaki