selecting distinct row by column in Datatable

May 17, 2008

this is an amasing set of codes which can help programmers to query for distinct rows in datatable by column(s) from humancompiler. I did little bit of tweaking or match one of my projects needs.

Here i am posting the code below:

VB

Public Shared Function SelectDistinct(ByVal SourceTable As DataTable, ByVal ParamArray FieldNames() As String) As DataTable
Dim lastValues() As Object
Dim newTable As DataTable

If FieldNames Is Nothing OrElse FieldNames.Length = 0 Then
Throw New ArgumentNullException(“FieldNames”)
End If

lastValues = New Object(FieldNames.Length – 1) {}
newTable =
New DataTable

For Each field As String In FieldNames
newTable.Columns.Add(field, SourceTable.Columns(field).DataType)
Next

For Each Row As DataRow In SourceTable.Select(“”, String.Join(“, “, FieldNames))
If Not fieldValuesAreEqual(lastValues, Row, FieldNames) Then
newTable.Rows.Add(createRowClone(Row, newTable.NewRow(), FieldNames))

setLastValues(lastValues, Row, FieldNames)
End If
Next

Return newTable
End Function

Private Shared Function fieldValuesAreEqual(ByVal lastValues() As Object, ByVal currentRow As DataRow, ByVal fieldNames() As String) As Boolean
Dim areEqual As Boolean = True

For i As Integer = 0 To fieldNames.Length – 1
If lastValues(i) Is Nothing OrElse Not lastValues(i).Equals(currentRow(fieldNames(i))) Then
areEqual = False
Exit For
End If
Next

Return areEqual
End Function

Private Shared Function createRowClone(ByVal sourceRow As DataRow, ByVal newRow As DataRow, ByVal fieldNames() As String) As DataRow
For Each field As String In fieldNames
newRow(field) = sourceRow(field)
Next

Return newRow
End Function

Private Shared Sub setLastValues(ByVal lastValues() As Object, ByVal sourceRow As DataRow, ByVal fieldNames() As String)
For i As Integer = 0 To fieldNames.Length – 1
lastValues(i) = sourceRow(fieldNames(i))
Next
End Sub

C#

private static DataTable SelectDistinct(DataTable SourceTable, params string[] FieldNames)
{
object[] lastValues;
DataTable newTable;
DataRow[] orderedRows;

if (FieldNames == null || FieldNames.Length == 0)
throw new ArgumentNullException(“FieldNames”);

lastValues = new object[FieldNames.Length];
newTable =
new DataTable();

foreach (string fieldName in FieldNames)
newTable.Columns.Add(fieldName, SourceTable.Columns[fieldName].DataType);

orderedRows = SourceTable.Select(“”, string.Join(“, “, FieldNames));

foreach (DataRow row in orderedRows)
{
if (!fieldValuesAreEqual(lastValues, row, FieldNames))
{
newTable.Rows.Add(createRowClone(row, newTable.NewRow(), FieldNames));

setLastValues(lastValues, row, FieldNames);
}
}

return newTable;
}

private static bool fieldValuesAreEqual(object[] lastValues, DataRow currentRow, string[] fieldNames)
{
bool areEqual = true;

for (int i = 0; i < fieldNames.Length; i++)
{
if (lastValues[i] == null || !lastValues[i].Equals(currentRow[fieldNames[i]]))
{
areEqual =
false;
break;
}
}

return areEqual;
}

private static DataRow createRowClone(DataRow sourceRow, DataRow newRow, string[] fieldNames)
{
foreach (string field in fieldNames)
newRow[field] = sourceRow[field];

return newRow;
}

private static void setLastValues(object[] lastValues, DataRow sourceRow, string[] fieldNames)
{
for (int i = 0; i < fieldNames.Length; i++)
lastValues[i] = sourceRow[fieldNames[i]];
}

This can be also done in bit simpler manner below:

public static DataTable SelectDistinct(string[] pColumnNames, DataTable pOriginalTable)

{

DataTable distinctTable = new DataTable();

int numColumns = pColumnNames.Length;

for (int i = 0; i < numColumns; i++)

{

distinctTable.Columns.Add(pColumnNames[i], pOriginalTable.Columns[pColumnNames[i]].DataType);

}

Hashtable trackData = new Hashtable();

foreach (DataRow currentOriginalRow in pOriginalTable.Rows)

{

StringBuilder hashData = new StringBuilder();

DataRow newRow = distinctTable.NewRow();

for (int i = 0; i < numColumns; i++)

{

hashData.Append(currentOriginalRow[pColumnNames[i]].ToString());

newRow[pColumnNames[i]] = currentOriginalRow[pColumnNames[i]];

}

if (!trackData.ContainsKey(hashData.ToString()))

{

trackData.Add(hashData.ToString(), null);

distinctTable.Rows.Add(newRow);

}

}

return distinctTable;

}

However, there is even simpler code if you use dataview as below:

VB Code:

——————————————————

Public Function SelectDistinct(ByVal SourceTable As DataTable, ByVal ParamArray Columns() As String) As DataTable

Dim Result As DataTable = New DataTable()

If SourceTable IsNot Nothing Then

Dim DView As DataView = SourceTable.DefaultView

Try

Result = DView.ToTable(True, Columns)

Catch ex As Exception

End Try

End If

Return Result

End Function

——————————————————

C# Code:

——————————————————

public DataTable SelectDistinct(DataTable SourceTable, params string[] Columns) {

DataTable Result = new DataTable();

if (SourceTable != null) {

DataView DView = SourceTable.DefaultView;

try {

Result = DView.ToTable(true, Columns);

}

catch (Exception ex) {

}

}

return Result;

}

Well, thats about how to select distinct rows by column in datatable but then one should be remembered that create datatable takes memory spaces since they are virtual tables.


Follow

Get every new post delivered to your Inbox.