1
votes

Supprimer des objets de la liste

J'ai la liste suivante -

public List<edgeData> RemoveLinks(List<edgeData>() edgeList, int linkCount)
{
    var updatedEdgeData = new List<edgeData>();

    // logic

    return updatedEdgeData;
}

Je souhaite supprimer une entrée edgeData de edgeList lorsque la source collectivement est inférieur ou égal à linkCount.

Par exemple, construisez mon edgeData -

var newEdge = new edgeData();
newEdge.source = "James";
newEdge.target = 1;
edgeList.Add(newEdge);

var newEdge = new edgeData();
newEdge.source = "Greg";
newEdge.target = 2;
edgeList.Add(newEdge);

var newEdge = new edgeData();
newEdge.source = "James";
newEdge.target = 3;
edgeList.Add(newEdge);

Puis traitez pour supprimer les entrées qui sont inférieures ou égales à linkCount-

public class edgeData
{
    public string source { get; set; }
    public string target { get; set; }
}

var edgeList = new List<edgeData>();
var linkCount = 1;

Donc, dans l'exemple, l'entrée contenant "Greg" comme source serait supprimée car il ne s'est produit qu'une seule fois, ce qui est égal à linkCount.

J'ai essayé de faire cela avec une boucle for, mais cela est devenu incroyablement moche assez rapidement et je pense que Linq est la meilleure option, mais comment puis-je y parvenir? p>


3 commentaires

Qu'est-ce que tu as essayé jusque-là? De plus, votre code ne sera pas compilé, vous ne pouvez pas attribuer la valeur int à la chaîne


Il vaut la peine de mentionner votre identifiant unique d'un article de la collection. Je suppose que c'est une propriété source ?


edgeList.RemoveAll (edge ​​=> when_to_remove);


3 Réponses :


4
votes

Vous pouvez faire ce qui suit

edgeList.GroupBy(x=>x.source)
                   .Where(x=>x.Skip(linkCount).Any())
                   .SelectMany(x=>x)
                   .ToList()

Vous devez Grouper par la source et filtrer les groupes qui ont des éléments inférieurs au linkCount code>.

Veuillez également noter que selon OP, edgeData.target est une chaîne, mais votre code l'affiche sous forme de nombre. Espérons que ce soit une faute de frappe.

Mise à jour

Comme l'a souligné Harald, si la taille du groupe est énorme, vous pouvez également utiliser,

edgeList.GroupBy(x=>x.source)
                   .Where(x=>x.Count()>linkCount)
                   .SelectMany(x=>x)
                   .ToList();


2 commentaires

Si l'un de vos groupes a un million d'éléments et que linkCount a une valeur de 5, pourquoi Count () all million d'éléments? Utilisez plutôt Skip (5) .Any () .


@HaraldCoppoolse Merci de l'avoir signalé, nous avons mis à jour la réponse



0
votes

En gros, comptez simplement l'occurrence des noms, puis bouclez sur la liste et supprimez celui que vous n'aimez pas (pas assez de connexions)

        Dictionary<string, int> occurrence = new Dictionary<string, int>();
        foreach (edgeData edge in edgeList)
        {
            if (occurrence.ContainsKey(edge.source)) 
                occurrence[edge.source] += 1;
            else
                occurrence[edge.source] = 1;
        }

        int counter = 0;
        while(counter < edgeList.Count)
        {
            if (occurrence[edgeList[counter].source] < linkCount)
                edgeList.RemoveAt(counter);
            else 
                counter++;
        }


0 commentaires

1
votes

Je souhaite supprimer une entrée edgeData de edgeList lorsque la source est collectivement inférieure ou égale à linkCount.

Je pense que vous ne voulez dans votre résultat final que les éléments de votre séquence d'entrée qui ont une valeur de propriété Source qui apparaît plus de fois dans votre séquence que linkCount .

Donc, si linkCount vaut 5, vous ne voulez conserver ces enregistrements que là où il y a au moins cinq occurrences de cette Source dans la séquence d'entrée.

Pour cela, nous devons regrouper votre entrée en groupes avec la même valeur pour Source . Après cela, nous ne conservons que les groupes qui contiennent plus d'éléments que linkCount :

IEnumerable<EdgeData> result = edgeList.GroupBy( edgeItem => edgeItem.Source)

    // keep only the groups with enough elements:
    .Where(group => group.Skip(linkCount).Any())

    // Ungroup, so we get a neat sequence
    .SelectMany(group => group);

Le résultat de GroupBy est une séquence d'objets où chacun object implémente IGrouping . Cet objet est en lui-même une séquence de EdgeData , où chaque propriété Source a la même valeur. Cette valeur est dans la Key de l'IGrouping.

Après avoir créé les groupes, je ne garde que les groupes qui contiennent plus de linkCount éléments. Je fais cela, en sautant les premiers éléments LinkCount de la séquence que le groupe est, et s'il reste des éléments, alors apparemment le groupe a plus que des éléments linkCount.

Je ne veux pas utiliser Count (), car si votre groupe a un million d'éléments, ce serait une perte de puissance de traitement de compter tous ces éléments, si vous arrêtez de compter après avoir vu qu'il y en a plus que linkCount.

Le résultat du Where est une séquence de IGrouping Pour dégrouper, nous utilisons SelectMany , ce qui en fait une séquence soignée de EdgeData code> à nouveau.


1 commentaires

C'est une réponse excellente et informative avec du temps.