usuario recorrer por formulario eliminar dinamicamente dentro crear controles control como codigo botones agregar c# collections

recorrer - eliminar controles de un panel c#



La mejor manera de eliminar elementos de una colección (14)

¿Cuál es la mejor manera de abordar la eliminación de elementos de una colección en C #, una vez que se conoce el elemento, pero no su índice? Esta es una forma de hacerlo, pero parece poco elegante en el mejor de los casos.

//Remove the existing role assignment for the user. int cnt = 0; int assToDelete = 0; foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments) { if (spAssignment.Member.Name == shortName) { assToDelete = cnt; } cnt++; } workspace.RoleAssignments.Remove(assToDelete);

Lo que realmente me gustaría hacer es encontrar el elemento para eliminar por propiedad (en este caso, nombre) sin recorrer toda la colección y usar 2 variables adicionales.


¿Qué tipo es la colección? Si se trata de una lista, puede usar la útil "Eliminar todo":

int cnt = workspace.RoleAssignments .RemoveAll(spa => spa.Member.Name == shortName)

(Esto funciona en .NET 2.0. Por supuesto, si no tiene el compilador más nuevo, tendrá que usar "delegate (SPRoleAssignment spa) {return spa.Member.Name == shortName;}" en lugar del agradable compilador. sintaxis lambda)

Otro enfoque si no es una lista, pero sigue siendo una colección de ideas:

var toRemove = workspace.RoleAssignments .FirstOrDefault(spa => spa.Member.Name == shortName) if (toRemove != null) workspace.RoleAssignments.Remove(toRemove);

Esto requiere los métodos de extensión Enumerable. (Puede copiar los mono en, si está atrapado en .NET 2.0). Si se trata de una colección personalizada que no puede tomar un elemento, pero DEBE tomar un índice, algunos de los otros métodos Enumerable, como Seleccionar, le pasan el índice entero.


@smaclell preguntó por qué la iteración inversa era más eficiente en un comentario a @ sambo99.

A veces es más eficiente. Considere que tiene una lista de personas y desea eliminar o filtrar a todos los clientes con una calificación crediticia <1000;

Tenemos los siguientes datos

"Bob" 999 "Mary" 999 "Ted" 1000

Si tuviéramos que iterar hacia adelante, pronto nos meteríamos en problemas

for( int idx = 0; idx < list.Count ; idx++ ) { if( list[idx].Rating < 1000 ) { list.RemoveAt(idx); // whoops! } }

En idx = 0 eliminamos Bob , que luego desplaza todos los elementos restantes. La próxima vez a través del ciclo idx = 1, pero la lista [1] ahora es Ted lugar de Mary . Terminamos saltándonos a Mary por error. Podríamos usar un ciclo while, y podríamos introducir más variables.

O bien, solo iteramos al revés:

for (int idx = list.Count-1; idx >= 0; idx--) { if (list[idx].Rating < 1000) { list.RemoveAt(idx); } }

Todos los índices a la izquierda del elemento eliminado permanecen iguales, por lo que no se salta ningún elemento.

El mismo principio se aplica si recibe una lista de índices para eliminar de una matriz. Para mantener las cosas claras, debe ordenar la lista y luego eliminar los elementos del índice más alto al más bajo.

Ahora puede usar Linq y declarar lo que está haciendo de manera directa.

list.RemoveAll(o => o.Rating < 1000);

Para este caso de eliminación de un solo artículo, no es más eficiente iterar hacia adelante o hacia atrás. También puedes usar Linq para esto.

int removeIndex = list.FindIndex(o => o.Name == "Ted"); if( removeIndex != -1 ) { list.RemoveAt(removeIndex); }


Al igual que en el punto de vista de la Colección de diccionarios, he hecho esto.

Dictionary<string, bool> sourceDict = new Dictionary<string, bool>(); sourceDict.Add("Sai", true); sourceDict.Add("Sri", false); sourceDict.Add("SaiSri", true); sourceDict.Add("SaiSriMahi", true); var itemsToDelete = sourceDict.Where(DictItem => DictItem.Value == false); foreach (var item in itemsToDelete) { sourceDict.Remove(item.Key); }

Nota: El código anterior fallará en .Net Client Profile (3.5 y 4.5) y algunos usuarios mencionaron que está fallando para ellos en .Net4.0 y no están seguros de qué configuración está causando el problema.

Así que reemplace con el código a continuación (.ToList ()) para la declaración Where, para evitar ese error. "La colección fue modificada; la operación de enumeración no puede ejecutarse ".

var itemsToDelete = sourceDict.Where(DictItem => DictItem.Value == false).ToList();

Por MSDN desde .Net4.5 en adelante El perfil del cliente está descontinuado. http://msdn.microsoft.com/en-us/library/cc656912(v=vs.110).aspx


Aquí hay una forma bastante buena de hacerlo

http://support.microsoft.com/kb/555972

System.Collections.ArrayList arr = new System.Collections.ArrayList(); arr.Add("1"); arr.Add("2"); arr.Add("3"); /*This throws an exception foreach (string s in arr) { arr.Remove(s); } */ //where as this works correctly Console.WriteLine(arr.Count); foreach (string s in new System.Collections.ArrayList(arr)) { arr.Remove(s); } Console.WriteLine(arr.Count); Console.ReadKey();


Esta es mi solución genérica

public static IEnumerable<T> Remove<T>(this IEnumerable<T> items, Func<T, bool> match) { var list = items.ToList(); for (int idx = 0; idx < list.Count(); idx++) { if (match(list[idx])) { list.RemoveAt(idx); idx--; // the list is 1 item shorter } } return list.AsEnumerable(); }

¡Parecería mucho más simple si los métodos de extensión admiten pasar por referencia! uso:

var result = string[]{"mike", "john", "ali"} result = result.Remove(x => x.Username == "mike").ToArray(); Assert.IsTrue(result.Length == 2);

EDITAR: garantizó que la lista de bucles sigue siendo válida incluso cuando se eliminan elementos al disminuir el índice (idx).


Hay otro enfoque que puede tomar dependiendo de cómo esté usando su colección. Si está descargando las asignaciones una vez (por ejemplo, cuando se ejecuta la aplicación), podría traducir la colección sobre la marcha en una tabla hash donde:

shortname => SPRoleAssignment

Si haces esto, cuando quieras eliminar un elemento por nombre corto, todo lo que tienes que hacer es eliminar el elemento de la tabla hash por clave.

Desafortunadamente, si carga estas SPRoleAssignments mucho, obviamente no va a ser más rentable en términos de tiempo. Las sugerencias que otras personas hicieron sobre el uso de Linq serían buenas si está utilizando una nueva versión de .NET Framework, pero, de lo contrario, deberá apegarse al método que está utilizando.


La mejor manera de hacerlo es mediante el uso de linq.

Clase de ejemplo:

public class Product { public string Name { get; set; } public string Price { get; set; } }

Consulta Linq:

var subCollection = collection1.RemoveAll(w => collection2.Any(q => q.Name == w.Name));

Esta consulta eliminará todos los elementos de collection1 si Name coincide con cualquier elemento Name from collection2

Recuerde utilizar: using System.Linq;


Muchas buenas respuestas aquí; Me gustan especialmente las expresiones lambda ... muy limpias. Sin embargo, fui negligente al no especificar el tipo de Colección. Esta es una SPRoleAssignmentCollection (de MOSS) que solo tiene Remove (int) y Remove (SPPrincipal), no el práctico RemoveAll (). Entonces, me he decidido por esto, a menos que haya una mejor sugerencia.

foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments) { if (spAssignment.Member.Name != shortName) continue; workspace.RoleAssignments.Remove((SPPrincipal)spAssignment.Member); break; }


Para hacerlo mientras recorre la colección y no para obtener la modificación de una excepción de colección, este es el enfoque que he tomado en el pasado (observe el .ToList () al final de la colección original, esto crea otra colección en la memoria , entonces puedes modificar la colección existente)

foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments.ToList()) { if (spAssignment.Member.Name == shortName) { workspace.RoleAssignments.Remove(spAssignment); } }


Para una estructura simple de listas, la forma más eficiente parece ser utilizar la implementación de predicado RemoveAll.

P.ej.

workSpace.RoleAssignments.RemoveAll(x =>x.Member.Name == shortName);

Las razones son:

  1. El método Predicate / Linq RemoveAll se implementa en List y tiene acceso a la matriz interna que almacena los datos reales. Cambiará los datos y redimensionará la matriz interna.
  2. La implementación del método RemoveAt es bastante lenta y copiará todo el conjunto de datos subyacente en una nueva matriz. Esto significa que la iteración inversa es inútil para List

Si estás atascado implementando esto en la era pre c # 3.0. Tienes 2 opciones.

  • La opción fácil de mantener. Copie todos los elementos coincidentes en una nueva lista y cambie la lista subyacente.

P.ej.

List<int> list2 = new List<int>() ; foreach (int i in GetList()) { if (!(i % 2 == 0)) { list2.Add(i); } } list2 = list2;

O

  • La opción complicada ligeramente más rápida, que implica desplazar todos los datos de la lista cuando no coinciden y luego cambiar el tamaño de la matriz.

Si está eliminando cosas con mucha frecuencia de una lista, quizás otra estructura como HashTable (.net 1.1) o un Dictionary (.net 2.0) o un HashSet (.net 3.5) sean más adecuadas para este propósito.


Primero guarde sus artículos, luego elimínelos.

var itemsToDelete = Items.Where(x => !!!your condition!!!).ToArray(); for (int i = 0; i < itemsToDelete.Length; ++i) Items.Remove(itemsToDelete[i]);

GetHashCode() anular GetHashCode() en su clase de elementos.


Si RoleAssignments es una List<T> puede usar el siguiente código.

workSpace.RoleAssignments.RemoveAll(x =>x.Member.Name == shortName);


Si desea acceder a los miembros de la colección por una de sus propiedades, puede considerar usar un Dictionary<T> o KeyedCollection<T> lugar. De esta forma no tienes que buscar el artículo que estás buscando.

De lo contrario, al menos podrías hacer esto:

foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments) { if (spAssignment.Member.Name == shortName) { workspace.RoleAssignments.Remove(spAssignment); break; } }


Si se trata de una ICollection entonces no tendrá un método RemoveAll . Aquí hay un método de extensión que lo hará:

public static void RemoveAll<T>(this ICollection<T> source, Func<T, bool> predicate) { if (source == null) throw new ArgumentNullException("source", "source is null."); if (predicate == null) throw new ArgumentNullException("predicate", "predicate is null."); source.Where(predicate).ToList().ForEach(e => source.Remove(e)); }

Basado en: http://phejndorf.wordpress.com/2011/03/09/a-removeall-extension-for-the-collection-class/