質問するログイン新規登録
C#

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

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

Q&A

解決済

3回答

43147閲覧

LINQで最大値ではなく、最大値を持つ要素の取得とforeach。

退会済みユーザー

退会済みユーザー

総合スコア0

C#

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

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

0グッド

2クリップ

投稿2018/07/23 05:29

0

2

前提・実現したいこと

LINQの勉強をしています。
LINQで最大値ではなく、最大値を持つ要素を取得したいです。
いくつか方法はあると思いますが、Max()を使うのがおそらく1番シンプルに書けると思うのですが、
その書き方のご教示をお願いします。

また、該当のソースコードのforeach文をLINQで書き換えることは可能ですか?
こちらのご教示もお願いします。

該当のソースコード

ファイルサイズの最大値をもつFileInfoの要素を取得したいです。
ファイルサイズの最大値そのものは取得できました。

C#

1  List<FileInfo> filelist = new List<FileInfo>(); 2 DirectoryInfo di = new DirectoryInfo(@"C:\Users\username\Desktop\testfolder"); 3 4 foreach (FileInfo fi in di.GetFiles()) 5 { 6 filelist.Add(fi); 7 } 8 9 //リストの中で最大値のファイルサイズを取得する。 10 long maxsize = filelist.Max(s => s.Length); 11 Console.WriteLine(maxsize); 12 13 //リストの中で最大値のファイルサイズを持つ要素を取得するにはどうすればいいですか? 14 //Maxを使って取得することはできますか?

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

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

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

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

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

guest

回答3

0

質問者さんが先のスレッドで使っていた OrderByDescending を使ってできると思います。

以下のような感じ。

FileInfo max = filelist.OrderByDescending(s => s.Length).FirstOrDefault();

もっとスマートな方法はあるかもしれませんが。

投稿2018/07/23 07:46

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2018/07/23 09:41 編集

ご回答ありがとうございます。 勉強になりました。 Maxを使って簡単にできるかと思っていたのですが、そのような方法はなさそうなんですね。 ありがとうございます。
退会済みユーザー

退会済みユーザー

2018/07/23 11:43

Max を使うと、かなり無理やりっぽいですが、以下のような感じでしょうか。これももっとスマートな方法はあるかもしれませんが。 FileInfo max = filelist.Find(s => s.Length == filelist.Max(p => p.Length));
退会済みユーザー

退会済みユーザー

2018/07/23 15:53

ご回答ありがとうございます。 Maxの条件に一致するものをFindで見つけるという書き方ができるのですね。 ご教示いただきありがとうございます。
guest

0

ベストアンサー

一番シンプルに書くならAggregate<T,T,T>だと思います。
Listの要素にIComparable<T>を実装すれば引数無しのMaxが使えますが、FileInfoではそのままでは使えませんね。

C#

1 2filelist.Aggregate((result, next) => result.Length > next.Length ? result : next); 3

追記
無理矢理FileInfoにIComparableを実装するならこんな感じでしょうか。
自作クラスなら自然な形で実装できるのですが・・・

余談ですが、FileInfoに拡張メソッドでCompareToを定義してみましたがやはりダメでした。

C#

1 2filelist.Select(p => new FileInfoWrapper(p)).Max().FileInfo; 3 4class FileInfoWrapper : IComparable<FileInfoWrapper> 5{ 6 public FileInfo FileInfo { get; } 7 public FileInfoWrapper(FileInfo fileInfo) => FileInfo = fileInfo; 8 9 public int CompareTo(FileInfoWrapper other) 10 { 11 if (FileInfo.Length == other.FileInfo.Length) 12 { 13 return 0; 14 } 15 else if (FileInfo.Length > other.FileInfo.Length) 16 { 17 return 1; 18 } 19 else 20 { 21 return -1; 22 } 23 } 24} 25

投稿2018/07/23 06:50

編集2018/07/23 09:21
YamakawaJunichi

総合スコア632

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

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

退会済みユーザー

退会済みユーザー

2018/07/23 07:11

ご回答ありがとうございます。 Listの要素にIComparable<T>を実装するやり方も気になっていたので、ご教示いただけませんか?
YamakawaJunichi

2018/07/23 09:23

IComparable<T>実装パターンを追記しました。 FileInfoがsealedなためにこのような形になっています。
退会済みユーザー

退会済みユーザー

2018/07/23 09:40

ご回答ありがとうございます。 勉強になりました。 ありがとうございます。
guest

0

LINQで最大値ではなく、最大値を持つ要素を取得したいです。

.NET6以降MaxByが追加されたので、非常に簡単になりました^^
Enumerable.MaxBy メソッド (System.Linq) | Microsoft Learn

また、該当のソースコードのforeach文をLINQで書き換えることは可能ですか?

わざわざリストに入れる必要はないですね。
EnumerateFilesから、そのままLinqに繋げればいいでしょう。
DirectoryInfo.EnumerateFiles メソッド (System.IO) | Microsoft Learn


Listの要素にIComparable<T>を実装するやり方も気になっていたので、ご教示いただけませんか?

こちらも.NET6以降MaxIComparer<T>を渡すオーバーロードが追加されています。
Enumerable.Max メソッド (System.Linq) | Microsoft Learn

cs

1//var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "testfolder"); 2var path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); 3 4var maxBy = new DirectoryInfo(path) 5 .EnumerateFiles() 6 .MaxBy(s => s.Length); 7 8Console.WriteLine(maxBy?.Name ?? "empty files"); 9 10 11var max = new DirectoryInfo(path) 12 .EnumerateFiles() 13 .Max(new FileInfoComparer()); 14 15Console.WriteLine(max?.Name ?? "empty files"); 16 17class FileInfoComparer : Comparer<FileInfo> 18{ 19 public override int Compare(FileInfo? x, FileInfo? y) 20 => Comparer<long?>.Default.Compare(x?.Length, y?.Length); 21}

最大値の要素が複数あった場合、MaxByは要素ひとつしか返しません。
すべて列挙したいならMaxByは使えません。

一度Maxを求めてWhereするとか、GroupByしてMaxByするとかひと工夫必要です。
面倒だったらMoreLINQMaximaを使うのも手です。

cs

1using static MoreLinq.Extensions.MaximaExtension; 2 3int[] array = [-5, 3, -1, 5]; 4Console.WriteLine(array.MaxBy(Math.Abs)); // -5 5 6var absMax = array.Max(Math.Abs); 7Console.WriteLine(string.Join(", ", array.Where(x => Math.Abs(x) == absMax))); // -5, 5 8Console.WriteLine(string.Join(", ", array.GroupBy(Math.Abs).MaxBy(g => g.Key)!)); // -5, 5 9Console.WriteLine(string.Join(", ", array.Maxima(Math.Abs))); // -5, 5

LINQ で最小値・最大値を柔軟に求める
c# - Linq MaxBy with all elements? - Stack Overflow
c# - MaxBy() is there a way to get multiple max values? - Stack Overflow

投稿2025/07/22 15:39

編集2025/07/23 06:21
TN8001

総合スコア10166

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

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

dodox86

2025/07/23 03:34 編集

ご回答の意図から外れたコメントかもしれませんが、 > var maxBy = new DirectoryInfo(path) > .EnumerateFiles() > .MaxBy(s => s.Length); だけだと、ファイルサイズMaxのファイルが複数存在しても1つしか取得しないようです。当初の質問投稿時の意図から推察すると、恐らくそれでは困るかと。 外したコメントであったらすみません。[一部修正済み]
TN8001

2025/07/23 06:21

> だけだと、ファイルサイズMaxのファイルが複数存在しても1つしか取得しないようです。当初の質問投稿時の意図から推察すると、恐らくそれでは困るかと。 LINQのMaxに言及している時点で「最大の1個でいい」と思い込んでいましたが、要素(FileInfo)が欲しいなら全部出たほうがいいに決まってますよね^^; タイトル的にもそこは回収しておくべきでしたね(でもあんまキレイな方法ないんよなw 補足ありがとうございます^^
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問