![](/img/trans.png)
[英]get list from xml using linq based on true if there is no true then select false condition tag element in c#
[英]Get List<> element position in c# using LINQ
我有一個帶數字的列表,我想使用 LINQ 找到最小值(不是值)的 position
例子:
var lst = new List<int>() { 3, 1, 0, 5 };
現在我正在尋找一個 function 返回我
output = 2
因為列表中的最小值是 position 2。
var list = new List<int> { 3, 1, 0, 5 };
int pos = list.IndexOf(list.Min()); // returns 2
正如您特別要求提供 LINQ 解決方案,而您得到的只是非 LINQ 解決方案,這是一個 LINQ 解決方案:
List<int> values = new List<int> { 3, 1, 0, 5 };
int index =
values
.Select((n, i) => new { Value = n, Index = i })
.OrderBy(n=>n.Value)
.First()
.Index;
然而,這並不意味着 LINQ 是這個問題的最佳解決方案......
使用更復雜的代碼,這會表現得更好:
int index =
values
.Select((n, i) => new { Value = n, Index = i })
.Aggregate((a,b) => a.Value < b.Value ? a : b)
.Index;
為了獲得最佳性能,您將使用普通循環遍歷項目,同時跟蹤最低的項目:
int index = 0, value = values[0];
for (int i = 1; i < values.Length; i++) {
if (values[i] < value) {
value = values[i];
index = i;
}
}
捕捉位置的最佳方式是通過FindIndex
該函數僅適用於 List<>
例子
int id = listMyObject.FindIndex(x => x.Id == 15);
如果您有枚舉器或數組,請使用這種方式
int id = myEnumerator.ToList().FindIndex(x => x.Id == 15);
要么
int id = myArray.ToList().FindIndex(x => x.Id == 15);
我同意 LINQ 不是這個問題的最佳解決方案,但這是 O(n) 的另一個變體。 它不排序,只遍歷列表一次。
var list = new List<int> { 3, 1, 0, 5 };
int pos = Enumerable.Range(0, list.Count)
.Aggregate((a, b) => (list[a] < list[b]) ? a : b); // returns 2
var data = new List<int> { 3, 1, 0, 5 };
var result = Enumerable.Range(0, data.Count).OrderBy(n => data[n]).First();
一個列表可以包含多個等於最小值的元素(見下文)。
我編寫的通用擴展方法.FindEveryIndex()
適用於整數、字符串……並且非常靈活,因為您可以將條件指定為 Lambda 表達式。
另一個優點是它返回匹配條件的所有索引的列表,而不僅僅是第一個元素。
關於您的問題:最小值可以返回為:
var lst = new List<int>() { 1, 2, 1, 3, 4, 1 }; // example list
var minimum = lst.Min(); // get the minumum value of lst
var idx = lst.FindEveryIndex(x => x == minimum); // finds all indices matching condition
Console.WriteLine($"Output: {String.Join(',', idx.ToArray())}"); // show list of indices
它將返回索引 0、2 和 5,因為lst1
的最小值是1
:
輸出:0,2,5
示例 2:
void Main()
{
// working with list of integers
var lst1 = new List<int>() { 1, 2, 1, 3, 4, 1 };
lst1.FindEveryIndex(x => x==1).Dump("Find 1"); // finds indices: [0, 2, 5]
lst1.FindEveryIndex(x => x==2).Dump("Find 2"); // finds index: [1]
lst1.FindEveryIndex(x => x==9).Dump("Find 9"); // returns [-1]
// working with list of strings
var lst2 = new List<string>() { "A", "B", "A", "C", "D", "A"};
lst2.FindEveryIndex(x => x=="A").Dump("Find A"); // finds indices: [0, 2, 5]
lst2.FindEveryIndex(x => x=="B").Dump("Find B"); // finds index: [1]
lst2.FindEveryIndex(x => x=="X").Dump("Find X"); // returns [-1]
}
擴展類:
public static class Extension
{
// using System.Collections.Generic;
public static IEnumerable<int> FindEveryIndex<T>(this IEnumerable<T> items,
Predicate<T> predicate)
{
int index = 0; bool found = false;
foreach (var item in items)
{
if (predicate(item))
{
found = true; yield return index;
};
index++;
}
if (!found) yield return -1;
}
}
注意:將兩個代碼片段復制到 LinqPad C# 程序中,它會立即生效。
或者,使用DotNetFiddle在線運行它。
List<int> data = new List<int>();
data.AddRange(new[] { 3, 1, 0, 5 });
Console.WriteLine(data.IndexOf(data.Min()));
int min = 0;
bool minIsSet = false;
var result = ints
.Select( (x, i) => new {x, i}
.OrderBy(z => z.x)
.Select(z =>
{
if (!minIsSet)
{
min = z.x;
minIsSet = true;
}
return z;
}
.TakeWhile(z => z.x == min)
.Select(z => z.i);
我不一定推薦這種 CPS 風格的代碼,但它可以工作並且是 O(n),與使用 OrderBy 的解決方案不同:
var minIndex = list.Aggregate(
new { i = 0, mini = -1, minv = int.MaxValue },
(min, x) => (min.minv > x)
? new { i = min.i + 1, mini = min.i, minv = x }
: new { i = min.i + 1, mini = min.mini, minv = min.minv })
.mini;
如果您想要最后一個最小副本,而不是第一個,請將 > 更改為 >=。
使用 .minv 獲取最小值,或者兩者都不使用以獲取具有索引和最小值的二元組。
我等不及 .NET 在 4.0 中獲得元組了。
如果在列表中查找 1 個或多個具有相同值的元素的 position:
using System.Linq;
List<int> lst = new List<int>() { 3, 1, 0, 5, 0 }; // works for int array as well
List<int> ids = lst.Select((value, index) => new { value, index })
.Where(x => x.value == 0)
.Select(x => x.index)
.ToList(); // returns 2, 4
List<int>.Enumerator e = l.GetEnumerator();
int p = 0, min = int.MaxValue, pos = -1;
while (e.MoveNext())
{
if (e.Current < min)
{
min = e.Current;
pos = p;
}
++p;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.