編集:以下のコードにいくつかの改善を加えました。次DataTable.IndexOf(otherTable)
の拡張メソッドは、テーブルが別のテーブルのサブセットであるかどうかをチェックします。
比較で無視する列名を渡すことができます。列の順序は重要ではありませんが、順序は重要ですDataRows
(サブセットの行の順序は同じである必要があります)。
DataRows
の等しいサブセットが見つからなかった場合、または等しいサブセットが開始するメインテーブル(this
拡張機能内)の最初のインデックスが見つからなかった場合は、-1を返します。
public static class DataTableExtensions
{
public static int IndexOf(this DataTable tblMain, DataTable tblSub, params String[] ignoreColumns)
{
if (tblMain == null)
throw new ArgumentNullException("tblMain");
if (tblSub.Rows.Count == 0)
throw new ArgumentException("tblSub must not be empty", "tblSub");
if (tblSub.Rows.Count > tblMain.Rows.Count)
return -1;
IEnumerable<String> relevantColumnNames = tblSub.Columns.Cast<DataColumn>()
.Select(c => c.ColumnName)
.Except(ignoreColumns)
.ToArray();
foreach (String colName in relevantColumnNames)
if (!tblMain.Columns.Contains(colName))
return -1;
for (int mainRowIndex = 0; tblMain.Rows.Count - mainRowIndex >= tblSub.Rows.Count; mainRowIndex++)
{
// check if current window is equal to tblSub
bool allRowsAreEqual = true;
for (int windowIndex = mainRowIndex; windowIndex < tblSub.Rows.Count + mainRowIndex; windowIndex++)
{
DataRow currentMain = tblMain.Rows[windowIndex];
DataRow currentSub = tblSub.Rows[windowIndex - mainRowIndex];
bool allFieldsAreEqual = relevantColumnNames.All(colName =>
Object.Equals(currentMain[colName], currentSub[colName]));
if (!allFieldsAreEqual)
{
allRowsAreEqual = false;
break; // continue with next window in main-table
}
}
if (allRowsAreEqual)
return mainRowIndex;
}
// no equal window found in main-table
return -1;
}
}
サンプルデータ:
var TblSub = new DataTable();
var TblMain = new DataTable();
TblSub.Columns.Add("FeeID", typeof(int));
TblSub.Columns.Add("Amount", typeof(int));
TblSub.Columns.Add("FeeItem", typeof(string));
TblSub.Columns.Add("Type", typeof(char));
TblMain.Columns.Add("FeeID", typeof(int));
TblMain.Columns.Add("Amount", typeof(int));
TblMain.Columns.Add("FeeItem", typeof(string));
TblMain.Columns.Add("Type", typeof(char));
TblSub.Rows.Add(10, 7500, "Admission Free", 'T');
TblSub.Rows.Add(10, 900, "Annual Fee", 'T');
TblSub.Rows.Add(10, 150, "Application Free", 'T');
TblSub.Rows.Add(10, 850, "Boy's Uniform", 'T');
TblSub.Rows.Add(10, 50, "Computer Free", 'R');
TblMain.Rows.Add(9, 8500, "Admission Free", 'T');
TblMain.Rows.Add(9, 950, "Annual Fee", 'T');
TblMain.Rows.Add(9, 150, "Application Free", 'T');
TblMain.Rows.Add(9, 850, "Boy's Uniform", 'T');
TblMain.Rows.Add(9, 50, "Computer Free", 'R');
TblMain.Rows.Add(10, 7500, "Admission Free", 'T');
TblMain.Rows.Add(11, 900, "Annual Fee", 'T');
TblMain.Rows.Add(11, 150, "Application Free", 'T');
TblMain.Rows.Add(11, 850, "Boy's Uniform", 'T');
TblMain.Rows.Add(11, 50, "Computer Free", 'R');
次のように使用できます。
int firstIndex = TblMain.IndexOf(TblSub, "FeeID");
if (firstIndex == -1)
Console.Write("Second table does not contain first table");
else
Console.Write("Second table does contain first table at row-index " + firstIndex);
出力は次のとおりです。
2番目のテーブルには、行インデックス5の最初のテーブルが含まれています
古いアプローチ:
2つのDataTableが等しいかどうかをチェックする次のメソッドを使用できます。
using System.Linq
を追加する必要がありますEnumerable.SequenceEqual
。Linqを使用できない場合は、ループを使用してください。
static bool TablesEqual(DataTable table1, DataTable table2, params int[] skipColumns)
{
if (table1.Rows.Count != table2.Rows.Count)
return false;
for (int i = 0; i < table1.Rows.Count; i++)
{
var array1 = table1.Rows[i].ItemArray
.Where((obj, index) => !skipColumns.Contains(index));
var array2 = table2.Rows[i].ItemArray
.Where((obj, index) => !skipColumns.Contains(index)); ;
if (!array1.SequenceEqual(array2))
{
return false;
}
}
return true;
}
次のように、無視する列のインデックスを渡す必要があります。
bool allEqual = TablesEqual(t1, t2); // all equal
bool equalIgnore0 = TablesEqual(t1, t2, 0); // ignore first column
bool equalIgnore0and2 = TablesEqual(t1, t2, 0, 2); // ignore first and third column