質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

3回答

1716閲覧

C#、DatetimeOffset(Datetime)型のソートについて

heroherohero

総合スコア38

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2019/08/26 23:50

編集2019/08/27 03:54

UWP(Prism version6.3)で、アプリの開発を行っております。

下記内容を実装したいと思い、色々と調べてみたのですが、実装方法が分からなかったため、質問させていただきます。

実現したいこと

DatimeOffset型の3つのメンバが含まれたListが存在し、そのDatimeOffset型の3つのメンバをもとに、Listのソートを行いたいと考えております。また、このDatimeOffset型のメンバは、NULL許容でもありますので、そちらの対応も行いたいと思っております。

※すみません、自分の意図が正しく伝わっていなかったもしれないため、今一度、追記をさせていただきます(2019.8.27.12:53)
1.TakenTimeで降順のソートを行う。(nullのものは一番最後に来る。)
2.(1.TakenTimeが同じだった場合)CreatedAtで、降順にソートを行う。(nullのものは一番最後に来る。)
3.(2.CreateAtが同じだった場合)UpdatedAtで、降順にソートを行う。(nullのものは一番最後に来る。)
この順でソートを行いたいと思っております。今一度、アドバイスございましたら、よろしくお願いいたします。

調べたこと/試したこと

単一のメンバーの場合は、下記で実現できることを確認済みです。

c#

1PhotoList.Sort((a, b) => Nullable.Compare(b.TakenTime, a.TakenTime));

null許容に対しては、参考文献を参考に下記のようにしたらうまくいくのではないかと思いましたが、できませんでした。
※実際に実現したいことは、下記のようなソートになります。

c#

1PhotoList.OrderBy(x => x.TakenTime ).ThenBy( x => x.TakenTime ).ThenBy(x=> x.CreatedAt).ThenBy(x=> x.UpdatedAt);

参考文献

http://www.remember-the-time.xyz/2016/08/c-sharp-linq-orderby-include-null.html

以上、アドバイスいただけますと幸いです。

どうぞ、よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2019/08/27 00:36 編集

できませんでしたというのはどういうことですか? まったく順序が変わらないのか、エラーが発生するのか、思ったような順序にならないのか、コンパイル自体できないのか、など、「できない」には多くの種類があります。実際にこちらでサンプルデータを作って試さなければいけませんか?
heroherohero

2019/08/27 03:17

すみません、質問の聞き方が悪く失礼いたしました。 今回、できなかなったというのは、「思ったようにソートができなかった」の意味になります。 思ったようにソートができなかったというよりも、ソードが全くされていないない状態と同じでした。 お手数ですが、よろしくお願いいたします。
Zuishin

2019/08/27 04:38

hihijiji さんの方法でできるはずですが、全くされていないということは、ソート済みのものを破棄しているんじゃないかと思います。 PhotoList = PhotoList.OrderBy(... のように、ソートしたものを受け取らなければいけません。
heroherohero

2019/08/27 13:24

ありがとうございます。はい、Zuishinさんのおっしゃるように、自分が試した方法で、ソートしたものを受け取っていなかったため、全くソートがされない事態に陥ってしまっていました。結論、自分で最初に書いていたものをもとに実現することができました。ご協力いただき、ありがとうございました。
guest

回答3

0

C#

1class PhotoInfomation 2{ 3 public DateTimeOffset? TakenTime { get; set; } 4 public DateTimeOffset? CreatedAt { get; set; } 5 public DateTimeOffset? UpdatedAt { get; set; } 6} 7 8List<PhotoInfomation> PhotoList { get; set; }

こんな定義だった場合にnullを後ろに持ってくるにはこんな感じ

C#

1var sortedInfo = PhotoList 2 .OrderBy(p => p.CreatedAt?.DateTime ?? DateTime.MaxValue) 3 .ThenBy(p => p.TakenTime?.DateTime ?? DateTime.MaxValue) 4 .ThenBy(p => p.UpdatedAt?.DateTime ?? DateTime.MaxValue)

投稿2019/08/27 01:32

hihijiji

総合スコア4150

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

heroherohero

2019/08/27 03:52

コメント、ありがとうございます。 また、Classまで記載していただき、ありがとうございます。 はい、hihijijiさんが書いてくださっている、Classの前提で間違いございません。 この後、試させていただきます。 すみません、自分の意図が正しく伝わっていなかったもしれないため、今一度、追記をさせていただきますと、 1.TakenTimeで降順のソートを行う。(nullのものは一番最後に来る。) 2.(1.TakenTimeが同じだった場合)CreatedAtで、降順にソートを行う。(nullのものは一番最後に来る。) 3.(2.CreateAtが同じだった場合)UpdatedAtで、降順にソートを行う。(nullのものは一番最後に来る。) この順でソートを行いたいと思っております。今一度、アドバイスございましたら、よろしくお願いいたします。
hihijiji

2019/08/27 06:22

OrderByDescending、ThenByDescendingになるだけです。 OrderByDescending(p => p.TakenTime?.DateTime ?? DateTime.MinValue)… 以下はわかりますよね?
heroherohero

2019/08/27 13:14

ありがとうございます。こちら教えていただいたものを参考に以下のように書いてみましたが、NULLの値が先頭にきてしまい、期待通りにソートすることができませんでした。(NULLが一番後ろにきたら、それ以外のソートは期待通りにできておりました。)もしかしたら、私の方法が間違っていますでしょうか。よろしくお願いいたします。 var sortedInfo = PhotoList .OrderByDescending(p => p.TakenTime?.DateTime ?? DateTime.MaxValue) .ThenByDescending(p => p.CreatedAt?.DateTime ?? DateTime.MaxValue) .ThenByDescending(p => p.UpdatedAt?.DateTime ?? DateTime.MaxValue);
hihijiji

2019/08/29 01:03

DateTime.MaxValue → DateTime.MinValue になります。
guest

0

自己解決

C#

1var photoImfo = PhotoList 2 .OrderByDescending(x => x.TakenTime.HasValue) 3 .ThenByDescending(x => x.TakenTime) 4 .ThenByDescending(x => x.CreatedAt.HasValue) 5 .ThenByDescending(x => x.CreatedAt) 6 .ThenByDescending(x => x.UpdatedAt.HasValue) 7 .ThenByDescending(x => x.UpdatedAt); 8 9PhotoList = photoImfo.ToList();

※自分がやりたいことを実現することはできましたが、パフォーマンスは恐らく全然良くないと思います。なので、もっと良い案がありましたら、コメントいただけますと幸いです。よろしくお願いいたします!

投稿2019/08/27 13:31

heroherohero

総合スコア38

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

要は「リストで複数の並べ替え条件を扱えるようにしたい」という話であれば WindowsCommunityToolkitの

AdvancedCollectionView
https://docs.microsoft.com/en-us/windows/communitytoolkit/helpers/advancedcollectionview

こちらのSortDescriptionsを利用すればいけるんじゃないでしょうか。条件1・条件2を投入した場合に、まず条件1で並び替えをし、条件1で同値だったものは条件2で並び替える、といった並べ替え管理ができます。

SortDescriptionに対してICompererを渡すこともできるのでnullの場合の挙動もコントロールできると思います。

ちなみに、AdvnacedCollectionViewはObservableCollectionと同等のインターフェイスを実装しているので、SortDescriptionsを設定しておけば、あとから要素を追加しても並び替えが実行されたコレクションを得られます。

並び替えの自動実行に関する注意点として、コンストラクタのisLiveShapingオプションを有効にしないと、後から追加した場合の並べ替えが自動実行されません。途中で複数のアイテムを投入する場合にはisLiveShapingをfalseにして、手動でRefresh()を呼び出すか、またはisLiveShapingをtrueにしたままでもDeferRefresh()を活用することで「追加や削除などを一括処理した後に更新する」といった操作をusingスコープでまとめられます。

投稿2019/08/27 01:06

tor4kichi

総合スコア763

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

heroherohero

2019/08/27 13:28 編集

色々と、詳細に教えていただき、ありがとうございます。アドバイスをいただいて恐縮ですが、いただいたアドバイスを試す前に、問題が解決することができてしまいました。そのため、「AdvancedCollectionView」について、試すことはできておりませんが、機会を見つけて利用させていただきます。 引き続き、よろしくお願いいたします。お忙しい中、アドバイスありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問