简体   繁体   English

从列表中删除对象

[英]Remove objects from list

I have the following list -我有以下清单 -

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

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

I want to remove an edgeData entry from edgeList when the source collectively occurs less than or equal to linkCount .我想删除的edgeData从条目edgeList当源共同出现小于或等于linkCount

For example build up my edgeData -例如建立我的 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);

Then process to remove entries that occur less or equal to linkCount -然后处理删除出现的小于或等于linkCount -

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

    // logic

    return updatedEdgeData;
}

So in the example the entry containing "Greg" as the source would be removed because he has occurred only once which is equal to the linkCount.所以在这个例子中,包含“Greg”作为源的条目将被删除,因为他只出现了一次,这等于linkCount。

I tried doing this with a for loop however this got incredibly ugly pretty quickly and believe Linq is the best option however how can I achieve this?我尝试使用 for 循环执行此操作,但是这很快变得非常难看,并且相信 Linq 是最佳选择,但是我该如何实现呢?

You could do the following您可以执行以下操作

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

You need to Group by the source and filter out the groups which has items less than the linkCount .您需要Group由源和筛选出具有项小于组linkCount

Please also note that according to OP, edgeData.target is a string, but your code shows it as number.另请注意,根据 OP, edgeData.target是一个字符串,但您的代码将其显示为数字。 Hopefully it is a typo.希望这是一个错字。

Update更新

As Harald pointed out, if the size of group is huge, you could alternatively use,正如 Harald 指出的那样,如果组的规模很大,你也可以使用,

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

I want to remove an edgeData entry from edgeList when the source collectively occurs less than or equal to linkCount.当源总体出现小于或等于 linkCount 时,我想从 edgeList 中删除一个 edgeData 条目。

I think you want in your end-result only those items from your input sequence that have a value of property Source that occurs more times in your sequence than linkCount .我认为您希望在最终结果中只需要输入序列中具有属性Source值的项目,该值在您的序列中出现的次数比linkCount

So if linkCount equals 5, you only want to keep those records where there are at least five occurences of this Source in the input sequence.因此,如果linkCount等于 5,则您只想保留在输入序列中此Source至少出现 5 次的那些记录。

For this we need to group your input into groups with the same value for Source .为此,我们需要将您的输入分组为具有相同Source值的组。 After that we only keep those groups that have more elements that linkCount in them:之后,我们只保留那些包含更多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);

The result of the GroupBy is a sequence of object where each object implements IGrouping<string, EdgeData> . GroupBy 的结果是一个对象序列,其中每个对象都实现IGrouping<string, EdgeData> This object is in itself a sequence of EdgeData , where every Source property has the same value.这个对象本身就是一个EdgeData序列,其中每个Source属性都具有相同的值。 This value is in the Key of the IGrouping.该值位于 IGrouping 的Key中。

After making the groups, I keep only the groups that have more than linkCount items in them.创建组后,我只保留其中包含超过 linkCount 个项目的组。 I do this, by skipping the first LinkCount items of the sequence that the group is, and if there are any items left, then apparently the group has more than linkCount items.我这样做是通过跳过组所在序列的第一个 LinkCount 项目,如果还有任何项目,那么显然该组有多个 linkCount 项目。

I don't want to use Count(), because if your group has a zillion items, it would be a waste of processing power to count all those items, if you can stop counting after you've seen that there are more than linkCount.我不想使用 Count(),因为如果您的组有无数个项目,那么计算所有这些项目会浪费处理能力,如果您可以在看到超过 linkCount 后停止计数.

The result of the Where is a sequence of IGrouping<string, EdgeData> To ungroup, we use SelectMany , which makes it a neat sequence of EdgeData again. Where 的结果是IGrouping<string, EdgeData>的序列 要取消分组,我们使用SelectMany ,这使其再次成为EdgeData的整洁序列。

Basically just count the occurrnce of the names, then loop on the list and remove the one that you don't like (not enough connections)基本上只需计算名称的出现次数,然后在列表中循环并删除您不喜欢的名称(连接不足)

        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++;
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM