Return 数据表中存在的值的行和列索引
Return line and column Index of a value that exists in dataTable
this link 中提供的解决方案非常有用:
DataColumn[] columns = tbl.Columns.Cast<DataColumn>().ToArray();
bool anyFieldContainsPepsi = tbl.AsEnumerable()
.Any(row => columns.Any(col => row[col].ToString() == "PEPSI"));
- 但我需要 return,而不是 bool,"found" 值的索引。我应该试试 this idea 吗?请注意,我确实需要行 Number/Index 和列 Number/Index.
此时我的代码:
bool find = csvDataOnlyHeader.Rows.Cast<DataRow>().Any(r => r.ItemArray.Any(c => c.ToString().Contains("SN:")));
DataColumn[] columns = csvDataOnlyHeader.Columns.Cast<DataColumn>().ToArray();
bool anyFieldContains = csvDataOnlyHeader.AsEnumerable()
.Any(row => columns.Any(col => row[col].ToString() == "SN:"));
我需要什么:
- 在整个 DataTable 中搜索特定字符串(不关心列名或位置)。
- Return 包含此字符串的位置的索引(或多个索引)。 (即第 2 行第 4 列)
Select
有一个变体,可以让您捕获索引。
var matchingIndexes = csvDataOnlyHeader.Rows.Cast<DataRow>()
.Select((r, index) => new
{
isMatch = r.ItemArray.Any(c => c.ToString().Contains("SN:")),
index
})
.Where(e => e.isMatch)
.Select(e => e.index);
var firstMatch = matchingIndexes.FirstOrDefault();
为了避免 firstMatch
具有 0
(意味着第一个匹配项是数组的第零个元素)和 0
(意味着没有匹配的索引)之间的歧义,你可以将结果转换为可为空的整数:
...
.Select(e => (int?)e.index)
...
或者您可以使用我的 CallMeMaybe 库来获取 Maybe<int>
:
var firstMatch = matchingIndexes.FirstMaybe();
您应该能够使用 DataRowCollection
类型的 IndexOf
方法获取行索引,或者@StriplingWarrior 指出 lambda 表达式的索引参数,如果行的索引在原始枚举对你来说足够可靠。
var columns = tbl.Columns.Cast<DataColumn>().ToList();
var enumerableRowCollection = tbl.AsEnumerable();
var results = enumerableRowCollection
.Select((row, index) =>
{
var column = columns.FirstOrDefault(col => row[col].ToString() == "PEPSI");
return new
{
Column = column,
ColumnIndex = column != null ? columns.IndexOf(column) : -1,
Row = row,
RowIndex = index
};
})
.Where(x => x.Column != null)
.ToList();
for (var i = 0; i < results.Count(); i++)
{
var result = results[i];
Console.WriteLine($"Result {i}");
Console.WriteLine($"RowIndex: {result.RowIndex}");
Console.WriteLine($"ColumnIndex: {result.ColumnIndex}");
}
this link 中提供的解决方案非常有用:
DataColumn[] columns = tbl.Columns.Cast<DataColumn>().ToArray();
bool anyFieldContainsPepsi = tbl.AsEnumerable()
.Any(row => columns.Any(col => row[col].ToString() == "PEPSI"));
- 但我需要 return,而不是 bool,"found" 值的索引。我应该试试 this idea 吗?请注意,我确实需要行 Number/Index 和列 Number/Index.
此时我的代码:
bool find = csvDataOnlyHeader.Rows.Cast<DataRow>().Any(r => r.ItemArray.Any(c => c.ToString().Contains("SN:")));
DataColumn[] columns = csvDataOnlyHeader.Columns.Cast<DataColumn>().ToArray();
bool anyFieldContains = csvDataOnlyHeader.AsEnumerable()
.Any(row => columns.Any(col => row[col].ToString() == "SN:"));
我需要什么:
- 在整个 DataTable 中搜索特定字符串(不关心列名或位置)。
- Return 包含此字符串的位置的索引(或多个索引)。 (即第 2 行第 4 列)
Select
有一个变体,可以让您捕获索引。
var matchingIndexes = csvDataOnlyHeader.Rows.Cast<DataRow>()
.Select((r, index) => new
{
isMatch = r.ItemArray.Any(c => c.ToString().Contains("SN:")),
index
})
.Where(e => e.isMatch)
.Select(e => e.index);
var firstMatch = matchingIndexes.FirstOrDefault();
为了避免 firstMatch
具有 0
(意味着第一个匹配项是数组的第零个元素)和 0
(意味着没有匹配的索引)之间的歧义,你可以将结果转换为可为空的整数:
...
.Select(e => (int?)e.index)
...
或者您可以使用我的 CallMeMaybe 库来获取 Maybe<int>
:
var firstMatch = matchingIndexes.FirstMaybe();
您应该能够使用 DataRowCollection
类型的 IndexOf
方法获取行索引,或者@StriplingWarrior 指出 lambda 表达式的索引参数,如果行的索引在原始枚举对你来说足够可靠。
var columns = tbl.Columns.Cast<DataColumn>().ToList();
var enumerableRowCollection = tbl.AsEnumerable();
var results = enumerableRowCollection
.Select((row, index) =>
{
var column = columns.FirstOrDefault(col => row[col].ToString() == "PEPSI");
return new
{
Column = column,
ColumnIndex = column != null ? columns.IndexOf(column) : -1,
Row = row,
RowIndex = index
};
})
.Where(x => x.Column != null)
.ToList();
for (var i = 0; i < results.Count(); i++)
{
var result = results[i];
Console.WriteLine($"Result {i}");
Console.WriteLine($"RowIndex: {result.RowIndex}");
Console.WriteLine($"ColumnIndex: {result.ColumnIndex}");
}