Удалить объекты из списка - PullRequest
1 голос
/ 21 февраля 2020

У меня есть следующий список -

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

Так что в Например, запись, содержащая «Грег» в качестве источника, будет удалена, потому что он произошел только один раз, что равно linkCount.

Я попытался сделать это с помощью для l oop, однако это стало невероятно уродливо довольно быстро и я считаю, что Linq - лучший вариант, как мне этого добиться?

Ответы [ 3 ]

4 голосов
/ 21 февраля 2020

Вы можете сделать следующее

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

Вам необходимо Group по источнику и отфильтровать группы, у которых есть элементы меньше, чем linkCount.

Обратите также внимание согласно OP, edgeData.target является строкой, но ваш код показывает ее как число. Надеемся, что это опечатка.

Обновление

Как отметил Харальд, если размер группы огромен, вы можете альтернативно использовать,

edgeList.GroupBy(x=>x.source)
                   .Where(x=>x.Skip(linkCount).Any())
                   .SelectMany(x=>x)
                   .ToList()
1 голос
/ 21 февраля 2020

Я хочу удалить запись edgeData из edgeList, когда общий источник данных меньше или равен linkCount.

Я думаю, что вы хотите, чтобы в конечном результате только те элементы из вашего входная последовательность со значением свойства Source, которое встречается в вашей последовательности больше раз, чем linkCount.

Так что, если linkCount равно 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 имеет одинаковое значение. Это значение находится в Key IGrouping.

После создания групп я сохраняю только те группы, в которых больше элементов linkCount. Я делаю это, пропуская первые элементы LinkCount в последовательности, в которой находится группа, и если в ней остались какие-либо элементы, то, очевидно, в группе больше элементов linkCount.

Я не хочу использовать Count (), потому что если в вашей группе есть миллион единиц, подсчет всех этих элементов будет пустой тратой вычислительной мощности, если вы можете прекратить считать после того, как увидите, что их больше, чем linkCount.

результат Where является последовательностью IGrouping<string, EdgeData>. Чтобы разгруппировать, мы используем SelectMany, что делает его аккуратной последовательностью EdgeData снова.

0 голосов
/ 21 февраля 2020

В основном просто посчитайте вхождение имен, затем l oop в списке и удалите то, что вам не нравится (недостаточно соединений)

        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++;
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...