valores repetidos quitar filas encontrar eliminar duplicados duplicadas datos cruzar condiciones condicion con como combinar checar c# datatable duplicates

c# - repetidos - ¿Cuál es la mejor manera de eliminar duplicados de una tabla de datos?



quitar duplicados en excel con condicion (12)

"Esta tabla de datos se está creando al leer un archivo CSV y no desde un DB".

Así que ponga una restricción única en las cuatro columnas en la base de datos, y las inserciones que estén duplicadas debajo de su diseño no entrarán. A menos que decida fallar en lugar de continuar cuando esto ocurra, pero esto seguramente puede configurarse en su script de importación de CSV.

Revisé todo el sitio y busqué en Google, pero no pude encontrar una solución simple a este problema.

Tengo una tabla de datos que tiene alrededor de 20 columnas y 10K filas. Necesito eliminar las filas duplicadas en esta tabla de datos basada en 4 columnas clave. ¿.Net no tiene una función que hace esto? La función más cercana a lo que estoy buscando es datatable.DefaultView.ToTable (cierto, matriz de columnas para mostrar), pero esta función hace una distinción en todas las columnas.

Sería genial si alguien pudiera ayudarme con esto.

EDITAR: Lo siento por no ser claro en esto. Esta tabla de datos se está creando al leer un archivo CSV y no desde un DB. Entonces, usar una consulta SQL no es una opción.


Encontrado esto en bytes.com :

Puede usar el proveedor JET 4.0 OLE DB con las clases en el espacio de nombres System.Data.OleDb para acceder al archivo de texto delimitado por comas (utilizando un DataSet / DataTable).

O puede usar Microsoft Text Driver para ODBC con las clases en el espacio de nombres System.Data.Odbc para acceder al archivo usando los controladores ODBC.

Eso le permitiría acceder a sus datos a través de consultas SQL, como otros propusieron.


La respuesta de Liggett78 es mucho mejor - esp. como el mío tuvo un error! Corrección de la siguiente manera ...

DELETE TableWithDuplicates FROM TableWithDuplicates LEFT OUTER JOIN ( SELECT PK_ID = Min(PK_ID), --Decide your method for deciding which rows to keep KeyColumn1, KeyColumn2, KeyColumn3, KeyColumn4 FROM TableWithDuplicates GROUP BY KeyColumn1, KeyColumn2, KeyColumn3, KeyColumn4 ) AS RowsToKeep ON TableWithDuplicates.PK_ID = RowsToKeep.PK_ID WHERE RowsToKeep.PK_ID IS NULL


Puede usar Linq para conjuntos de datos. Mira esto Algo como esto:

// Fill the DataSet. DataSet ds = new DataSet(); ds.Locale = CultureInfo.InvariantCulture; FillDataSet(ds); List<DataRow> rows = new List<DataRow>(); DataTable contact = ds.Tables["Contact"]; // Get 100 rows from the Contact table. IEnumerable<DataRow> query = (from c in contact.AsEnumerable() select c).Take(100); DataTable contactsTableWith100Rows = query.CopyToDataTable(); // Add 100 rows to the list. foreach (DataRow row in contactsTableWith100Rows.Rows) rows.Add(row); // Create duplicate rows by adding the same 100 rows to the list. foreach (DataRow row in contactsTableWith100Rows.Rows) rows.Add(row); DataTable table = System.Data.DataTableExtensions.CopyToDataTable<DataRow>(rows); // Find the unique contacts in the table. IEnumerable<DataRow> uniqueContacts = table.AsEnumerable().Distinct(DataRowComparer.Default); Console.WriteLine("Unique contacts:"); foreach (DataRow uniqueContact in uniqueContacts) { Console.WriteLine(uniqueContact.Field<Int32>("ContactID")); }


Si tiene acceso a Linq, creo que debería poder utilizar la funcionalidad de grupo integrada en la colección de memoria y seleccionar las filas duplicadas

Busque en Google para Linq Group por ejemplos


Use una consulta en lugar de funciones:

DELETE FROM table1 AS tb1 INNER JOIN (SELECT id, COUNT(id) AS cntr FROM table1 GROUP BY id) AS tb2 ON tb1.id = tb2.id WHERE tb2.cntr > 1


Este es un código muy simple que no requiere linq ni columnas individuales para hacer el filtro. Si todos los valores de las columnas de una fila son nulos, se eliminarán.

public DataSet duplicateRemoval(DataSet dSet) { bool flag; int ccount = dSet.Tables[0].Columns.Count; string[] colst = new string[ccount]; int p = 0; DataSet dsTemp = new DataSet(); DataTable Tables = new DataTable(); dsTemp.Tables.Add(Tables); for (int i = 0; i < ccount; i++) { dsTemp.Tables[0].Columns.Add(dSet.Tables[0].Columns[i].ColumnName, System.Type.GetType("System.String")); } foreach (System.Data.DataRow row in dSet.Tables[0].Rows) { flag = false; p = 0; foreach (System.Data.DataColumn col in dSet.Tables[0].Columns) { colst[p++] = row[col].ToString(); if (!string.IsNullOrEmpty(row[col].ToString())) { //Display only if any of the data is present in column flag = true; } } if (flag == true) { DataRow myRow = dsTemp.Tables[0].NewRow(); //Response.Write("<tr style=/"background:#d2d2d2;/">"); for (int kk = 0; kk < ccount; kk++) { myRow[kk] = colst[kk]; // Response.Write("<td class=/"table-line/" bgcolor=/"#D2D2D2/">" + colst[kk] + "</td>"); } dsTemp.Tables[0].Rows.Add(myRow); } } return dsTemp; }

Esto incluso puede usarse para eliminar datos nulos de la hoja de Excel.


Se debe tener en cuenta que se debe llamar a Table.AcceptChanges () para completar la eliminación. De lo contrario, la fila eliminada todavía está presente en DataTable con RowState establecido en Eliminado. Y Table.Rows.Count no se cambia después de la eliminación.


Prueba esto

Permítanos considerar dtInput es su tabla de datos con registros duplicados.

Tengo un nuevo DataTable dtFinal en el que quiero filtrar las filas duplicadas.

Entonces mi código será algo como a continuación.

DataTable dtFinal = dtInput.DefaultView.ToTable(true, new string[ColumnCount] {"Col1Name","Col2Name","Col3Name",...,"ColnName"});


No estaba interesado en usar la solución Linq anterior, así que escribí esto:

/// <summary> /// Takes a datatable and a column index, and returns a datatable without duplicates /// </summary> /// <param name="dt">The datatable containing duplicate records</param> /// <param name="ComparisonFieldIndex">The column index containing duplicates</param> /// <returns>A datatable object without duplicated records</returns> public DataTable duplicateRemoval(DataTable dt, int ComparisonFieldIndex) { try { //Build the new datatable that will be returned DataTable dtReturn = new DataTable(); for (int i = 0; i < dt.Columns.Count; i++) { dtReturn.Columns.Add(dt.Columns[i].ColumnName, System.Type.GetType("System.String")); } //Loop through each record in the datatable we have been passed foreach (DataRow dr in dt.Rows) { bool Found = false; //Loop through each record already present in the datatable being returned foreach (DataRow dr2 in dtReturn.Rows) { bool Identical = true; //Compare the column specified to see if it matches an existing record if (!(dr2[ComparisonFieldIndex].ToString() == dr[ComparisonFieldIndex].ToString())) { Identical = false; } //If the record found identically matches one we already have, don''t add it again if (Identical) { Found = true; break; } } //If we didn''t find a matching record, we''ll add this one if (!Found) { DataRow drAdd = dtReturn.NewRow(); for (int i = 0; i < dtReturn.Columns.Count; i++) { drAdd[i] = dr[i]; } dtReturn.Rows.Add(drAdd); } } return dtReturn; } catch (Exception) { //Return the original datatable if something failed above return dt; } }

Además, esto funciona en TODAS las columnas en lugar de un índice de columna específico:

/// <summary> /// Takes a datatable and returns a datatable without duplicates /// </summary> /// <param name="dt">The datatable containing duplicate records</param> /// <returns>A datatable object without duplicated records</returns> public DataTable duplicateRemoval(DataTable dt) { try { //Build the new datatable that will be returned DataTable dtReturn = new DataTable(); for (int i = 0; i < dt.Columns.Count; i++) { dtReturn.Columns.Add(dt.Columns[i].ColumnName, System.Type.GetType("System.String")); } //Loop through each record in the datatable we have been passed foreach (DataRow dr in dt.Rows) { bool Found = false; //Loop through each record already present in the datatable being returned foreach (DataRow dr2 in dtReturn.Rows) { bool Identical = true; //Compare all columns to see if they match the existing record for (int i = 0; i < dt.Columns.Count; i++) { if (!(dr2[i].ToString() == dr[i].ToString())) { Identical = false; } } //If the record found identically matches one we already have, don''t add it again if (Identical) { Found = true; break; } } //If we didn''t find a matching record, we''ll add this one if (!Found) { DataRow drAdd = dtReturn.NewRow(); for (int i = 0; i < dtReturn.Columns.Count; i++) { drAdd[i] = dr[i]; } dtReturn.Rows.Add(drAdd); } } return dtReturn; } catch (Exception) { //Return the original datatable if something failed above return dt; } }


Creo que esta debe ser la mejor manera de eliminar duplicados de Datatable utilizando Linq y el código moreLinq :

Linq

RemoveDuplicatesRecords(yourDataTable); private DataTable RemoveDuplicatesRecords(DataTable dt) { var UniqueRows = dt.AsEnumerable().Distinct(DataRowComparer.Default); DataTable dt2 = UniqueRows.CopyToDataTable(); return dt2; }

Artículo del blog: eliminar registros de filas duplicadas de DataTable Asp.net c #

MoreLinq

// Distinctby column name ID var valueDistinctByIdColumn = yourTable.AsEnumerable().DistinctBy(row => new { Id = row["Id"] }); DataTable dtDistinctByIdColumn = valueDistinctByIdColumn.CopyToDataTable();

Nota: moreLinq necesita agregar biblioteca.

En morelinq puede usar la función llamada DistinctBy en la que puede especificar la propiedad en la que desea encontrar objetos Distinct.

Artículo del blog: Uso del método más distintivo de LineinBy para eliminar registros duplicados


¿Cómo puedo eliminar filas duplicadas? . (Ajuste la consulta allí para unir sus 4 columnas clave)

EDITAR: con su nueva información, creo que la manera más fácil sería implementar IEqualityComparer <T> y usar Distinct en sus filas de datos. De lo contrario, si está trabajando con IEnumerable / IList en lugar de DataTable / DataRow, sin duda es posible con algunos LINQ-to-objects kung-fu.

EDITAR: ejemplo IEqualityComparer

public class MyRowComparer : IEqualityComparer<DataRow> { public bool Equals(DataRow x, DataRow y) { return (x.Field<int>("ID") == y.Field<int>("ID")) && string.Compare(x.Field<string>("Name"), y.Field<string>("Name"), true) == 0 && ... // extend this to include all your 4 keys... } public int GetHashCode(DataRow obj) { return obj.Field<int>("ID").GetHashCode() ^ obj.Field<string>("Name").GetHashCode() etc. } }

Puedes usarlo así:

var uniqueRows = myTable.AsEnumerable().Distinct(MyRowComparer);