C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

【C#】Linqを使用したソートについて

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■95485 / inTopicNo.1)  【C#】Linqを使用したソートについて
  
□投稿者/ つっちー (1回)-(2020/08/06(Thu) 19:18:01)

分類:[C#] 

2020/08/06(Thu) 21:58:48 編集(投稿者)
2020/08/06(Thu) 21:57:59 編集(投稿者)
2020/08/06(Thu) 21:57:54 編集(投稿者)

<pre><pre>お世話になっております。
Linqを使用したソートについてご助力いただけないでしょうか。

以下が実現したい内容、現在の状況になります。


■ソート条件
・第一ソートキー:年齢の昇順
・第二ソートキー:住所の昇順
※値が空白のものは、後ろに表示する

■ソート元データ
| 名前 | 年齢 | 住所 |
|あおやま| 10  |    |
|こすぎ |    |    |
|たなか | 15  |ナガノ |
|さとう |    |ナゴヤ |
|やまもと| 10  |ナハ  |

■理想
| 名前 | 年齢 | 住所 |
|やまもと| 10  |ナハ  |
|あおやま| 10  |    |
|たなか | 15  |ナガノ |
|さとう |    |ナゴヤ |
|こすぎ |    |    |

■ソース
var result = humans.OrderBy(i => i.Age).ThenBy(i => i.Address).ToList();

// 空の値が後ろにいくようソートする
result = result.OrderBy(i => string.IsNullOrWhiteSpace(i.Age)).ThenBy(i => string.IsNullOrWhiteSpace(i.Address)).ToList();

■実行結果
この場合にソートした結果として、以下のようになってしまいます。
| 名前 | 年齢 | 住所 |
|やまもと| 10  |ナハ  |
|たなか | 15  |ナガノ |
|あおやま| 10  |    |
|さとう |    |ナゴヤ |
|こすぎ |    |    |

■質問
Linqを使用して、理想の形に持っていくのは難しいでしょうか?
拡張メソッドでソートしなければ実現できないでしょうか?</pre></pre>

引用返信 編集キー/
■95486 / inTopicNo.2)  Re[1]: 【C#】Linqを使用したソートについて
□投稿者/ 魔界の仮面弁士 (2799回)-(2020/08/06(Thu) 21:18:06)
2020/08/06(Thu) 21:22:20 編集(投稿者)

No95485 (つっちー さん) に返信
> ※値が空白のものは、後ろに表示する

だとしたら
> ■理想
> | 名前 | 年齢 | 住所 |
> |あおやま| 10  |    |
> |やまもと| 10  |ナハ  |
これは逆なのでは?

> // 空の値が後ろにいくようソートする
> result = result.OrderBy(...
これだと最初のソート結果を破壊して、
別条件で新たに並べなおすことになってしまいます。

あと、今回は String のようですが、
それだと "1", "10", "2" のような
文字列ソートになるんじゃないかな…。
(未確認。移動中にスマホから書いてます)

もし、Age が Nullable<int> であれば
i => i.Age ?? int.MaxValue
で OrderBy を始めると良さそうですけれどね。

C# のバージョンが 7.0 以降であるのなら
i => int.TryParse(i, out int n) ? n : int.MaxValue
でどうでしょう。IsNullOrWhiteSpace を併用して、
空文字と非数値と数値で並びを変えても良いかもしれない。
引用返信 編集キー/
■95487 / inTopicNo.3)  Re[2]: 【C#】Linqを使用したソートについて
□投稿者/ つっちー (2回)-(2020/08/06(Thu) 22:12:11)
ご回答ありがとうございます。

>>■理想
>>| 名前 | 年齢 | 住所 |
>>|あおやま| 10  |    |
>>|やまもと| 10  |ナハ  |
> これは逆なのでは?
⇒申し訳ありません、ご指摘の通りです。
 編集しました。


>>// 空の値が後ろにいくようソートする
>>result = result.OrderBy(...
> これだと最初のソート結果を破壊して、
> 別条件で新たに並べなおすことになってしまいます。
> 
> あと、今回は String のようですが、
> それだと "1", "10", "2" のような
> 文字列ソートになるんじゃないかな…。
> (未確認。移動中にスマホから書いてます)
> 
> もし、Age が Nullable<int> であれば
> i => i.Age ?? int.MaxValue
> で OrderBy を始めると良さそうですけれどね。
⇒型に関しては、stringでお願いします。(例を急いで書いてしまったので変ですが・・・)

> C# のバージョンが 7.0 以降であるのなら
> i => int.TryParse(i, out int n) ? n : int.MaxValue
> でどうでしょう。IsNullOrWhiteSpace を併用して、
> 空文字と非数値と数値で並びを変えても良いかもしれない。
⇒string値の値の場合これってどうなるのでしょうか??
 i=> !string.IsNullOrWhiteSpace(i.Age) ? i.Age : "ん" とかでしょうか…?
 ちなみにc#のバージョンが 7.0以降であるのなら〜なんですが、ここの記述に関してどのように調べれば出てきますでしょうか?
 タプルについては見つけられたのですが。
 質問ばかりで申し訳ありませんがよろしくお願いいたします。

引用返信 編集キー/
■95488 / inTopicNo.4)  Re[3]: 【C#】Linqを使用したソートについて
□投稿者/ Hongliang (1075回)-(2020/08/06(Thu) 23:09:06)
> ⇒string値の値の場合これってどうなるのでしょうか??
>  i=> !string.IsNullOrWhiteSpace(i.Age) ? i.Age : "ん" とかでしょうか…?

つまり、"10"は"9"よりも前に来てほしいということですか?
であれば、お書きのようなコードでいいでしょう。

>  ちなみにc#のバージョンが 7.0以降であるのなら〜なんですが、ここの記述に関してどのように調べれば出てきますでしょうか?

出力変数宣言って言うらしいです。機能は知っていましたが用語は今知りました。
https://ufcpp.net/study/csharp/
ここなど、言語バージョンごとの新機能がよくまとまっていて参考になるかと思います。
引用返信 編集キー/
■95489 / inTopicNo.5)  Re[3]: 【C#】Linqを使用したソートについて
□投稿者/ 魔界の仮面弁士 (2800回)-(2020/08/07(Fri) 00:11:54)
2020/08/07(Fri) 00:23:48 編集(投稿者)

No95486 に投稿したコード、間違っていましたね…。orz
まぁ意図は伝わったようですが。


No95487 (つっちー さん) に返信
>>C# のバージョンが 7.0 以降であるのなら
>>i => int.TryParse(i, out int n) ? n : int.MaxValue
>>でどうでしょう。IsNullOrWhiteSpace を併用して、
>>空文字と非数値と数値で並びを変えても良いかもしれない。
> ⇒string値の値の場合これってどうなるのでしょうか??

たとえば、「基本的には数値順」だけれど、
「数値にできないものは、後回しにして文字列順」としつつ、
「IsNullOrWhiteSpace が true なものは一番最後」とするならば、
こんな感じに書けるかと思います。
("" と " " を同一視するか否かでも異なってきます)

.OrderBy(o => int.TryParse(o.Age, out var n) ? n : int.MaxValue)
.ThenBy(o => string.IsNullOrWhiteSpace(o.Age) ? "Last" : "First" )
.ThenBy(o => o.Age)
.ThenBy(p => string.IsNullOrWhiteSpace(p.Address) ? "Last" : "First")
.ThenBy(p => p.Address)
//.ThenBy(q => q.Name)


>  ちなみにc#のバージョンが 7.0以降であるのなら〜なんですが、
「c#」や「C♯」ではなく
「C#」と書くのが一般的です。


規定というわけでは無いのですが、規格(ECMA-334、ISO/IEC 23270、JIS X 3015)上は、
  LATIN CAPTITAL LETTER C (U+0043) の次に
  NUMBER SIGN # (U+0023) を書く。
ものとされているということで。


> ここの記述に関してどのように調べれば出てきますでしょうか?
Hongliang さんが紹介されている岩永さんのサイトがお奨めです。
引用返信 編集キー/
■95494 / inTopicNo.6)  Re[4]: 【C#】Linqを使用したソートについて
□投稿者/ つっちー (3回)-(2020/08/07(Fri) 13:21:58)
お答えいただいた、Hongliangさん、魔界の仮面弁士さん無事期待する結果を得ることができました!

Hongliangさん

>https://ufcpp.net/study/csharp/
>ここなど、言語バージョンごとの新機能がよくまとまっていて参考になるかと思います。
⇒サイトみました。
 分かりやすくまとまっていてよくわかりました。
 「出力変数宣言」覚えておきます、ご回答ありがとうございました。


魔界の仮面弁士さん

>.OrderBy(o => int.TryParse(o.Age, out var n) ? n : int.MaxValue)
>.ThenBy(o => string.IsNullOrWhiteSpace(o.Age) ? "Last" : "First" )
>.ThenBy(o => o.Age)
>.ThenBy(p => string.IsNullOrWhiteSpace(p.Address) ? "Last" : "First")
>.ThenBy(p => p.Address)
>//.ThenBy(q => q.Name)
⇒いただいたコードまんまで、期待する結果になること確認できました!
 とても丁寧に教えていただきありがとうございました。
 細かな部分まで教えていただけたので、知識としてとても役立ちそうです。

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ