第100回【JavaScript】辞書式ソート、ソート

現在取り組んでいるのは、paiza ラーニング問題集「Cランクレベルアップメニュー」になります。

はじめに

猫とキャンプと野球観戦と AWS が大好きな旦那、LeoSaki です。モフモフしたい。

JavaScript をゼロから勉強してみよう、のコーナー 100 回目です。

とうとう 3 桁回数いきました。日々 JavaScript と格闘して・・・あまり経ってない気がします。そして、普段はほとんど Python を使っている。基本的に趣味でやっているもののフロントを JavaScript で書きたい、という自己満足なので、地道にのんびり続けるつもりです。

それでは、今日も頑張ってみようと思います。

辞書式ソート (paizaランク D 相当)

正整数 n が与えられ、数のペアが n 個与えられます。各ペアの最初の数はりんごの個数を、その次の数はバナナの個数を表しています。これらの数のペアを以下の規則に従って、偉い順に並び替えてください。

1. ふたつのペアのりんごの数が異なる場合、りんごの数が多い方が偉い(この際、バナナの数は関係ない)。
2. りんごの数が同じである場合、バナナの数が多い方が偉い。


入力される値

n
a_1 b_1
...
a_n b_n

1 行目に正整数 n が、 2 行目から (n + 1) 行目には半角スペース区切りの数のペア a_1 b_1, …, a_n b_n が、それぞれ改行区切りで与えられます。

入力値最終行の末尾に改行が1つ入ります。


期待する出力

ペアを偉い順に並べ替え、改行区切りで n 行、順に出力してください。出力の各行は入力と同じく、 “a_i b_i" のように、りんごの個数とバナナの数が、この順に、半角スペースで区切られているものとします。

また、末尾に改行を入れ、余計な文字、空行を含んではいけません。


すべてのテストケースにおいて、以下の条件をみたします。

・ 1 ≤ n , a_i, b_i ≤ 50 (1 ≤ i ≤ n)


入力例

2
1 3
2 2

出力例

2 2
1 3

りんごとバナナ、どっちが偉いってなんだよ! 辞書式ソートというタイトルなので、連想配列にして考えてみる。

JavaScript
process.stdin.resume();
process.stdin.setEncoding('utf8');

var lines = [];
var reader = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout
});
reader.on('line', (line) => {
  lines.push(line);
});
reader.on('close', () => {
  const n = Number(lines[0]);
  const fruits = [];
  for (let i = 1; i <= n; i++) {
      const [a,b] = lines[i].split(/\s/).map(Number);
      fruits.push({'apple': a, 'banana': b});
  }
  const sortedItems = fruits.sort((a,b) => {
      if (a.apple === b.apple) {
          return b.banana - a.banana;
      }
      return b.apple - a.apple;
  });
  for (const obj of sortedItems) {
      console.log(obj.apple,obj.banana);
  }
});
Python
N = int(input())
ab = [None]*N
for i in range(N):
    a,b = map(int,input().split())
    ab[i] = [a,b]
ab.sort(reverse=True)
for a,b in ab:
    print(a,b)

ソート (paizaランク C 相当)

N 人の人々がおり、それぞれの人は金と銀を何キログラムか持っています。今は金の方が銀よりも価値が高いですが、ある日金と銀の価値が逆転して、人々の財産の多さは次のように決定されるようになりました。

1. 持っている銀が多い方が財産が多い。
2. 持っている銀が同じなら、持っている金が多い方が財産が多い。

それぞれの人が持っている金と銀のキログラム数が与えられるので、この規則にしたがって、財産を多い順に並び替えて出力してください。


入力される値

N
g_1 s_1
...
g_N s_N

1 行目には人々の数を表す整数 N が与えられ、 2 行目から (N + 1) 行目には、人々が持っている金の量 g_i と銀の量 s_i がそれぞれ半角スペース区切りで N 行与えられます (1 ≤ i ≤ N)。

入力値最終行の末尾に改行が1つ入ります。


期待する出力

上の規則に従って人々の財産を並び替え、入力と同じ形式で、各 g_i, s_i を半角スペース区切りで、財産が多い順に N 行出力してください。

また、末尾に改行を入れ、余計な文字、空行を含んではいけません。


すべてのテストケースにおいて、以下の条件をみたします。

・1 ≤ N ≤ 50
・0 ≤ g_i, s_i ≤ 50(1 ≤ i ≤ N)


入力例

2
2 1
1 2

出力例

1 2
2 1

金と銀の価値が入れ替わってしまったら、ちょっと悲しい。あまり影響はないけれど。

JavaScript
process.stdin.resume();
process.stdin.setEncoding('utf8');

var lines = [];
var reader = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout
});
reader.on('line', (line) => {
  lines.push(line);
});
reader.on('close', () => {
  const n = Number(lines[0]);
  const assets = [];
  for (let i = 1; i <= n; i++) {
      const [g,s] = lines[i].split(/\s/).map(Number);
      assets.push({'gold': g, 'silver': s});
  }
  const sortedItems = assets.sort((a,b) => {
      if (a.silver === b.silver) {
          return b.gold - a.gold;
      }
      return b.silver - a.silver;
  });
  for (const obj of sortedItems) {
      console.log(obj.gold,obj.silver);
  }
});
Python
N = int(input())
gs = [None]*N
for i in range(N):
    g,s = map(int,input().split())
    gs[i] = [s,g]
gs.sort(reverse=True)
for s,g in gs:
    print(g,s)

最後に

とても JavaScript らしく書けた気がして満足です。こういう考え方、こういう書き方は、JavaScript っぽいなぁと思いました。

模範解答的には、配列の中に配列を作って、インデックスで比較対象を取り出していました。それよりは分かりやすいのではないでしょうか。

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

Python の第100回はこちら