回答編集履歴

2

結論

2021/08/24 20:39

投稿

xebme
xebme

スコア1083

test CHANGED
@@ -50,46 +50,98 @@
50
50
 
51
51
 
52
52
 
53
- 属性がStringも含むソートもという要望に答えて、Ordering[Member]を用意します。
53
+ 属性がStringも含むソートもという要望に答えて、Ordering[Member]を用意します。結論にまとめました。
54
+
55
+
56
+
57
+ ---
58
+
59
+ **結論**
60
+
61
+
62
+
63
+ Ordering[Member]を使う方が汎用性が高いことがわかりました。理由は次のとおり。
64
+
65
+ - Memeberの項目のみならず、Memberから導出できるどんな項目をも、ソートキーにすることができる
66
+
67
+ - ソートキーの項目と個数を任意に指定できる
54
68
 
55
69
 
56
70
 
57
71
  ```Scala
58
72
 
59
- // メンバークラス定義
60
-
61
- case class Member(id: Int, name: String, height: Int, weight: Int)
73
+ case class Member(id:Int, name:String, height:Int, weight:Int)
62
74
 
63
75
 
64
76
 
65
- def comparator(i:Int):Ordering[Member] = i match {
77
+ def flexSort(members:Seq[Member], randomKey:Seq[Int]): Seq[Member] = {
66
78
 
67
- case 1 => Ordering.by(_.id)
79
+ def comparator(id: Int): Ordering[Member] = id match {
68
80
 
69
- case 2 => Ordering.by(_.name)
81
+ case 1 => Ordering.by(_.id)
70
82
 
71
- case 3 => Ordering.by(_.height)
83
+ case 2 => Ordering.by(_.name)
72
84
 
73
- case 4 => Ordering.by(_.weight)
85
+ case 3 => Ordering.by(-_.height)
74
86
 
75
- case _ => Ordering.by(_ => 0)
87
+ case 4 => Ordering.by(_.weight)
76
88
 
89
+ case _ => Ordering.by(_ => 0)
90
+
77
- }
91
+ }
92
+
93
+ val actualOrdering = randomKey.map(comparator(_)).reduce((a, o) => Ordering.comparatorToOrdering(a.thenComparing(o)))
94
+
95
+ members.sorted(actualOrdering)
96
+
97
+ }
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+ val Yamada = Member(1,"Yamada", 155,60)
106
+
107
+ val Yamada2 = Member(2,"Yamada", 170,63)
108
+
109
+ val Kawai = Member(3,"Kawai", 181,72)
110
+
111
+ val Yamada3 = Member(4,"Yamada", 155,55)
112
+
113
+ val list = Seq(Yamada, Yamada2, Kawai,Yamada3)
114
+
115
+ val randomKey = Seq(2,100,-3,3,4)
116
+
117
+ val result = flexSort(list,randomKey)
118
+
119
+ result.foreach(println(_))
78
120
 
79
121
  ```
80
122
 
81
123
 
82
124
 
83
- Ordering[Member]合成はちょっ技巧的ですが`java.util.Comaparator`変換て`Ordering`に戻します。`map`、`reduce`はすでに知っている前提。
125
+ 方法がベストか問われればも良い方法があるかもれない、と思います。
84
126
 
85
127
 
86
128
 
87
- ```Scala
129
+ **API**
88
-
89
- val comp = randomKey.map(comparator(_)).reduce((a,o) => Ordering.comparatorToOrdering(a.thenComparing(o)))
90
-
91
- ```
92
130
 
93
131
 
94
132
 
133
+ [scala.math.Ordering](https://www.scala-lang.org/api/2.13.3/scala/math/Ordering.html)
134
+
95
- Orderingは`sorted`の引数として渡します。
135
+ [object Ordering](https://www.scala-lang.org/api/2.13.3/scala/math/Ordering$.html)
136
+
137
+ [java.util.Comparator](https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/util/Comparator.html)
138
+
139
+
140
+
141
+ **参考**
142
+
143
+
144
+
145
+ [Scala ソート実験](http://www.ne.jp/asahi/hishidama/home/tech/scala/sample/sort.html)
146
+
147
+ [How to sort a list in Scala by two fields?](https://stackoverflow.com/questions/10027543/how-to-sort-a-list-in-scala-by-two-fields)

1

Ordering[Member]を追加

2021/08/24 20:39

投稿

xebme
xebme

スコア1083

test CHANGED
@@ -41,3 +41,55 @@
41
41
 
42
42
 
43
43
  `sortBy`だけでなく、`sorted`,`sortWith` を利用することも考えてください。
44
+
45
+
46
+
47
+ ---
48
+
49
+ **追記(Stringも含むソート)**
50
+
51
+
52
+
53
+ 属性がStringも含むソートもという要望に答えて、Ordering[Member]を用意します。
54
+
55
+
56
+
57
+ ```Scala
58
+
59
+ // メンバークラス定義
60
+
61
+ case class Member(id: Int, name: String, height: Int, weight: Int)
62
+
63
+
64
+
65
+ def comparator(i:Int):Ordering[Member] = i match {
66
+
67
+ case 1 => Ordering.by(_.id)
68
+
69
+ case 2 => Ordering.by(_.name)
70
+
71
+ case 3 => Ordering.by(_.height)
72
+
73
+ case 4 => Ordering.by(_.weight)
74
+
75
+ case _ => Ordering.by(_ => 0)
76
+
77
+ }
78
+
79
+ ```
80
+
81
+
82
+
83
+ Ordering[Member]の合成はちょっと技巧的ですが、`java.util.Comaparator`に変換して`Ordering`に戻します。`map`、`reduce`はすでに知っている前提。
84
+
85
+
86
+
87
+ ```Scala
88
+
89
+ val comp = randomKey.map(comparator(_)).reduce((a,o) => Ordering.comparatorToOrdering(a.thenComparing(o)))
90
+
91
+ ```
92
+
93
+
94
+
95
+ Orderingは`sorted`の引数として渡します。