从列表中删除对象

时间:2020-02-21 14:34:27

标签: c# list linq

我有以下列表-

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

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

当源集体出现小于或等于edgeData时,我想从edgeList中删除linkCount条目。

例如建立我的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);

然后删除出现次数小于或等于linkCount-

的条目的过程
public List<edgeData> RemoveLinks(List<edgeData>() edgeList, int linkCount)
{
    var updatedEdgeData = new List<edgeData>();

    // logic

    return updatedEdgeData;
}

因此在该示例中,将删除包含“ Greg”作为源的条目,因为该条目仅发生一次,该次数等于linkCount。

我尝试过使用for循环来执行此操作,但是这很快变得非常丑陋,并且相信Linq是最好的选择,但是我如何实现呢?

3 个答案:

答案 0 :(得分:4)

您可以执行以下操作

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

您需要按Group的来源,并过滤出项目少于linkCount的组。

还请注意,根据OP,edgeData.target是一个字符串,但是您的代码将其显示为数字。希望这是一个错字。

更新

正如Harald所指出的,如果组的规模很大,您可以选择使用,

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

答案 1 :(得分:1)

当源共同出现的次数小于或等于linkCount时,我想从edgeList中删除edgeData条目。

我认为您的最终结果中只需要输入序列中属性值为Source且与linkCount相比出现次数更多的那些项目。

因此,如果linkCount等于5,则只想将这些记录保留在输入序列中至少有5个出现此Source的地方。

为此,我们需要将您的输入分为Source具有相同值的组。之后,我们只保留其中包含更多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);

GroupBy的结果是一系列对象,其中每个对象都实现IGrouping<string, EdgeData>。该对象本身是EdgeData的序列,其中每个Source属性都具有相同的值。此值位于IGrouping的Key中。

进行分组后,我只保留其中包含linkCount项目以上的分组。通过跳过该组序列中的第一个LinkCount项,可以做到这一点,如果还有剩余项,则该组显然比linkCount项还多。

我不想使用Count(),因为如果您的组中有不计其数的项目,那么如果您在看到有超过linkCount。

Where是IGrouping<string, EdgeData>序列的结果。要取消分组,我们使用SelectMany,这又使其成为EdgeData的整齐序列。

答案 2 :(得分:0)

基本上只计算名称的出现次数,然后在列表上循环并删除您不喜欢的名称(连接不足)

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