配列(IEnumerable)の中から条件に当てはまる要素の添え字返却するLinq拡張
使わないようで、意外と使うので作っておくと、ちょっと便利?
public static class LinqExtensions
{
public static int FirstIndex<T>(this IEnumerable<T> ie, Predicate<T> match)
{
return ie.Select((tData, index) => new { tData, index }).First(arg => match(arg.tData)).index;
}
public static int? FirstIndexOrNull<T>(this IEnumerable<T> ie, Predicate<T> match)
{
return ie.Select((tData, index) => new { tData, index }).FirstOrDefault(arg => match(arg.tData))?.index;
}
}
使い方
class Program
{
static void Main(string[] args)
{
// [ 0][ 1][ 2][ 3][ 4][ 5][ 7][ 8][ 9][10][11][12]
var list = new[] { 1, 2, 3, 4, 5, 10, 20, 31, 32, 33, 34, 35};
var index1 = list.FirstIndex(i => i == 31);
Console.WriteLine("31が格納されているのは:" + index1 + "番目の要素でした。"); //出力:31が格納されているのは:7番目の要素でした。
var index2 = list.Select(i => i * 2).FirstIndex(i => i > 15);
Console.WriteLine("2倍した値で初めて15を超えるのは:" + index2 + "番目の要素でした。");//出力:2倍した値で初めて15を超えるのは:5番目の要素でした。
//var index3 = data.FirstIndex(i => i == 0); // LinqのFirst同様、存在しない場合は "ハンドルされていない例外: System.InvalidOperationException: シーケンスに、一致する要素は含まれてません" の例外発生
var index4 = list.FirstIndexOrNull(i => i == 0); //見つからない可能性がある場合はFirstOrDefaultのようにFirstOrNullを使用
if (index4.HasValue)
{
Console.WriteLine("0が格納されているのは:" + index4 + "番目の要素でした。");
}
else
{
Console.WriteLine("0は見つかりませんでした。");
}
}
}
public static class LinqExtensions
{
public static int FirstIndex<T>(this IEnumerable<T> ie, Predicate<T> match)
{
return ie.Select((tData, index) => new { tData, index }).First(arg => match(arg.tData)).index;
}
public static int? FirstIndexOrNull<T>(this IEnumerable<T> ie, Predicate<T> match)
{
return ie.Select((tData, index) => new { tData, index }).FirstOrDefault(arg => match(arg.tData))?.index;
}
}
class Program
{
static void Main(string[] args)
{
// [ 0][ 1][ 2][ 3][ 4][ 5][ 7][ 8][ 9][10][11][12]
var list = new[] { 1, 2, 3, 4, 5, 10, 20, 31, 32, 33, 34, 35};
var index1 = list.FirstIndex(i => i == 31);
Console.WriteLine("31が格納されているのは:" + index1 + "番目の要素でした。"); //出力:31が格納されているのは:7番目の要素でした。
var index2 = list.Select(i => i * 2).FirstIndex(i => i > 15);
Console.WriteLine("2倍した値で初めて15を超えるのは:" + index2 + "番目の要素でした。");//出力:2倍した値で初めて15を超えるのは:5番目の要素でした。
//var index3 = data.FirstIndex(i => i == 0); // LinqのFirst同様、存在しない場合は "ハンドルされていない例外: System.InvalidOperationException: シーケンスに、一致する要素は含まれてません" の例外発生
var index4 = list.FirstIndexOrNull(i => i == 0); //見つからない可能性がある場合はFirstOrDefaultのようにFirstOrNullを使用
if (index4.HasValue)
{
Console.WriteLine("0が格納されているのは:" + index4 + "番目の要素でした。");
}
else
{
Console.WriteLine("0は見つかりませんでした。");
}
}
}
もちろんIEnumerable<T>
なので
var strList = new[] {"abc", "def", "ghijkl", "mnoprstu", "vwxyz"};
var index5 = strList.FirstIndex(s => s.Length > 5);
Console.WriteLine("文字数が5文字を超えるのは:" + index5 + "番目の要素でした。");//出力:文字数が5文字を超えるのは:2番目の要素でした。
の様に、stringや自前のクラスでもウッドボール。
ところがどっこい
ここまで書いて、検証処理ちょっと走らせていたらListクラスには最初からFindIndexってメソッドがある事に気付きました。
なので、
var strList = new[] {"abc", "def", "ghijkl", "mnoprstu", "vwxyz"};
var index6 = strList.ToList().FindIndex(s => s.Length > 5);
Console.WriteLine("文字数が5文字を超えるのは:" + index6 + "番目の要素でした。");//出力:文字数が5文字を超えるのは:2番目の要素でした。
の様にToList()
を挟んであげれば、わざわざ自前で拡張クラス作る必要もないんですね・・・(ToListのコストがあるので優位性が無いわけではない…? 中で匿名クラスがnewされてるからむしろ不利か…。)
基礎ができてないって辛い。
Author And Source
この問題について(配列(IEnumerable)の中から条件に当てはまる要素の添え字返却するLinq拡張), 我々は、より多くの情報をここで見つけました https://qiita.com/divideby_zero/items/270c7c99c76af023b1df著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .