Удаление строк, содержащих одно и то же в списке - PullRequest
2 голосов
/ 14 сентября 2011

У меня есть список, который содержит что-то вроде этого:

C12 0402 123456 90
C133 0402 123456 90
C9 0402 123456 90
C132 0603 abcd 0
C54 0603 abcd 0
R FID1 fiducial 0
R FID2 fiducial 0
R FID3 fiducial 0
R FID4 fiducial 0

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

List<string> noDuplicatesList = new List<string>();

foreach (var line in theList)
{
    if (!noDuplicatesList.Contains(line.PartNumber)) //This is doing nothing...?
        noDuplicatesList.Add(line.Name + " " + line.PartDescription + " " line.PartNumber + " " + line.Rotation);
}

foreach (var line in noDuplicatesList)
{
    var splitLine = line.Split(' ');
    //Print out statements...
}

Вопрос

Как удалить / пропустить строки, содержащие одно и то же значение (в приведенном выше примере 123456, abcd, fiducial), так что он будет печатать только что-то вроде этого:

C12 0402 123456 90
C132 0603 abcd 0
R FID1 fiducial 0

Ответы [ 2 ]

3 голосов
/ 14 сентября 2011

Вы просто используете 3-й столбец в качестве условия группировки?

var noDuplicatesList = lines
    .GroupBy(l => l.PartNumber)
    .Select(group => group.First())

foreach(var item in noDuplicatesList)
    Console.WriteLine("{0} {1} {2} {3}", 
        item.Name,
        item.PartDescription,
        item.PartNumber,
        item.Rotation
    );

lines:

C12 0402 123456 90
C133 0402 123456 90
C9 0402 123456 90
C132 0603 abcd 0
C54 0603 abcd 0
R FID1 fiducial 0
R FID2 fiducial 0
R FID3 fiducial 0
R FID4 fiducial 0

lines.GroupBy(l => l.PartNumber):

{ C12 0402 123456 90, C133 0402 123456 90, C9 0402 123456 90}
{ C132 0603 abcd 0, C54 0603 abcd 0 }
{ R FID1 fiducial 0, R FID2 fiducial 0, R FID3 fiducial 0, R FID4 fiducial 0 }

lines.GroupBy(l => l.PartNumber).Select(group => group.First()):

C12 0402 123456 90
C132 0603 abcd 0
R FID1 fiducial 0
0 голосов
/ 14 сентября 2011

(При размышлении этот ответ предполагает, что в вашем списке учитывается порядок. Если порядок не имеет значения, просто используйте GroupBy, как указано в ответе ниже.)

Типичный "модульный"Для этого можно написать функцию PartitionBy, которая работает примерно так:

private static IEnumerable<ICollection<T>> PartitionBy<T, U>(
    IEnumerable<T> sequence, Func<T, U> selector)
{
    var buffer = new List<T>();

    using (var e = sequence.GetEnumerator())
    {
        if (!e.MoveNext())
            yield break;

        var priorValue = selector(e.Current);
        buffer.Add(e.Current);

        while (e.MoveNext())
        {
            var newValue = selector(e.Current);

            if (!object.Equals(selector(e.Current), priorValue))
            {
                priorValue = newValue;
                yield return buffer;
                buffer = new List<T>();
            }

            buffer.Add(e.Current);
        }
    }

    if (buffer.Any())
        yield return buffer;
}

Тогда ваша проблема может быть решена так:

var results = PartitionBy(objs, x => /* ... */).Select(list => list.First());

где ... однако вы получаете третье значение из объекта в вашем списке (например, x.Split()[2].)

...