使用 foreach 迭代时如何知道行索引?
Posted
技术标签:
【中文标题】使用 foreach 迭代时如何知道行索引?【英文标题】:How can I know a row index while iterating with foreach? 【发布时间】:2010-12-05 04:15:29 【问题描述】:在下一个示例中,我如何知道当前行索引?
foreach (DataRow temprow in temptable.Rows)
//this.text = temprow.INDEX????
【问题讨论】:
(C#) Get index of current foreach iteration的可能重复 【参考方案1】:你必须自己创建一个
var i = 0;
foreach (DataRow temprow in temptable.Rows)
this.text = i;
// etc
i++;
或者你可以只做一个 for 循环。
【讨论】:
+1,尽管我很少(如果有的话)提倡for
而不是foreach
。不同的存储机制在基于索引的查找(例如链表)上可能表现很差,而在直接枚举上表现很好。
@Adam 可以理解,测量可能是找出哪种方法更好的最好办法。【参考方案2】:
我在 MiscUtil 中有一个类型可以帮助解决这个问题 - SmartEnumerable
。这是一个愚蠢的名字,但它可以工作:) 有关详细信息,请参阅usage page,如果您使用的是 C# 3,您可以使其更简单:
foreach (var item in temptable.Rows.AsSmartEnumerable())
int index = item.Index;
DataRow value = item.Value;
bool isFirst = item.IsFirst;
bool isLast = item.IsLast;
【讨论】:
我假设temptable.Rows
是一个 DataTable,但是当我尝试执行您在这段代码中显示的操作时,它告诉我:DataRowCollection“不包含 AsSmartEnumerable 的定义”。那么temptable.Rows
是一个什么样的对象呢?帮助..
@J.Rodríguez 您是否在项目中包含了 MiscUtil,然后根据使用页面添加 using 指令?基本上它应该适用于任何IEnumerable<T>
是的,乔恩,它包括在内。对于列表是否有效,我不知道为什么它不允许在DataTable
中使用它例如:List<string> list = new List<string>(); foreach (var item in list.AsSmartEnumerable())
。
应该注意的是,我只使用了它的 MiscUtil:SmartEnumerable.cs
和 SmartEnumerableExt.cs
。我还缺少其他东西?
@J.Rodríguez 我的猜测是 Rows 只实现了非泛型接口。使用 LINQ 调用 Cast,然后在结果上调用 AsSmartEnumerable。【参考方案3】:
如果你可以使用Linq,你可以这样做:
foreach (var pair in temptable.Rows.Cast<DataRow>()
.Select((r, i) => new Row = r, Index = i))
int index = pair.Index;
DataRow row = pair.Row;
【讨论】:
伙计,我正要输入这个回复......哦,好吧【参考方案4】:你实际上没有。 foreach 的优点之一是你没有额外的代码处理增量和长度检查。
如果你想拥有自己的索引,你必须这样做
int rowindex = 0;
foreach (DataRow temprow in temptable.Rows)
//this.text = temprow.INDEX????
this.text = rowindex++;
【讨论】:
【参考方案5】:int rowIndex = temptable.Rows.IndexOf(temprow);
【讨论】:
我建议不要这样做。它可能比使用您自己的增量器花费更多。 我在测试时在长时间运行的 foreach 循环中设置了一个断点,并在监视窗口中使用它来帮助确定我还需要多长时间。足以进行调试:)【参考方案6】:使用标准的 foreach 循环是不可能的。最简单的方法是使用 for 循环
for ( int i = 0; i < temptable.Rows.Count; i++ )
DataRow temprow = (DataRow)temptable.Rows[i];
...
另一种选择是使用扩展方法
public static void ForEachIndex<T>(this IEnumerable<T> e, Action<T,int> del)
var i = 0;
foreach ( var cur in e )
del(cur,i);
...
temptable.Rows.Cast<DataRow>.ForEachIndex((cur,index)
...
);
【讨论】:
【参考方案7】:嘿,我想有一个更快的方法。无需迭代! 首先,为 DataRow 的 Friend RowID 字段声明一个静态变量:
Private Shared RowIDFieldInfo As System.Reflection.FieldInfo = GetType(DataRow).GetField("_rowID", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance)
那么你需要做的就是使用它:
RowIDFieldInfo.GetValue(MyDataRow) - 1
我在使用或过滤后没有对此进行测试。 就我而言,我不需要这样做,所以这是可行的。
【讨论】:
【参考方案8】:迟到总比没有好...
foreach (DataRow temprow in temptable.Rows)
temptable.Rows.IndexOf(temprow);
【讨论】:
【参考方案9】:写入任意单元格编号并获取行索引
foreach (var item in datagridview.Rows)
//TextBox1.Text= item.Cells[0].RowIndex.ToString();
【讨论】:
【参考方案10】:要么使用for循环,要么使用整数跟随:
int count =0;
foreach (DataRow temprow in temptable.Rows)
//count is the index of the row in the array temptable.Rows
//this.text = temprow.INDEX????
++count;
【讨论】:
【参考方案11】:你可以使用标准的for
循环来获取索引
for(int i=0; i<temptable.Rows.Count; i++)
var index = i;
var row = temptable.Rows[i];
【讨论】:
【参考方案12】:虽然 LFSR 的答案是正确的,但我很确定在几乎任何集合/列表上调用 .IndexOf 都会枚举列表,直到找到匹配的行。对于大型 DataTable,这可能会很慢。
for (i = 0; i
【讨论】:
【参考方案13】:使用索引而不是使用列名检索数据的替代方法
foreach (DataRow temprow in temptable.Rows)
String col1 = temprow[0].ToString().Trim();
String col2 = temprow[1].ToString().Trim();
希望对你有帮助
【讨论】:
以上是关于使用 foreach 迭代时如何知道行索引?的主要内容,如果未能解决你的问题,请参考以下文章
集合foreach迭代时,边迭代边删除,只能使用迭代器删除,不能使用集合删除,否则会导致并发修改异常for-each和Iterator的选择