Очистить дубликаты и их экземпляры из списка - PullRequest
1 голос
/ 03 мая 2020

У меня есть модель данных, подобная этой:

    public class AmpFile
    {
        public string filename { get; set; }
        public string actualpath { get; set; }
    }

Теперь у меня есть такой список:

[ list member 1 ]    -    filename:  "testfile1.jpg"    -    actualpath:  "C:\testpath\testfile1.jpg" 
[ list member 2 ]    -    filename:  "brickwall.jpg"    -    actualpath:  "C:\testpath\brickwall.jpg" 
[ list member 3 ]    -    filename:  "mydata.txt"    -    actualpath:  "D:\mydata.txt" 
[ list member 4 ]    -    filename:  "testfile1.jpg"    -    actualpath:  "E:\demo\testfile1.jpg" 
[ list member 5 ]    -    filename:  "mydata.txt"    -    actualpath:  "F:\somefolder\mydata.txt" 
[ list member 6 ]    -    filename:  "testfile1.jpg"    -    actualpath:  "F:\somefolder\testfile1.jpg" 
[ list member 7 ]    -    filename:  "testfile2.jpg"    -    actualpath:  "F:\somefolder\testfile2.jpg" 
[ list member 7 ]    -    filename:  "testfile3.jpg"    -    actualpath:  "D:\testfile3.jpg" 

Теперь я хочу найти дубликаты каждого члена, и если есть его дубликат, я хочу удалить дубликаты + саму ссылку, поэтому я хочу добиться результата:

[ list member 1 ]    -    filename:  "brickwall.jpg"    -    actualpath:  "C:\testpath\brickwall.jpg" 
[ list member 2 ]    -    filename:  "testfile2.jpg"    -    actualpath:  "F:\somefolder\testfile2.jpg" 
[ list member 3 ]    -    filename:  "testfile3.jpg"    -    actualpath:  "D:\testfile3.jpg" 

Как я могу это сделать?

Ответы [ 6 ]

4 голосов
/ 03 мая 2020

Вы можете сделать это с помощью Linq, используя Сгруппировать по и отфильтровать все элементы с count == 1, как в следующем коде:
1 - Подготовить список ampFile:

List<AmpFile> ampFiles = new List<AmpFile>
{
    new AmpFile{filename="testfile1.jpg",actualpath="C:\\testpath\\testfile1.jpg"},
    new AmpFile{filename="brickwall.jpg",actualpath="C:\\testpath\\brickwall.jpg"},
    new AmpFile{filename="mydata.txt",actualpath="D:\\mydata.txt"},
    new AmpFile{filename="testfile1.jpg",actualpath="E:\\demo\testfile1.jpg"},
    new AmpFile{filename="mydata.txt",actualpath="F:\\somefolder\\mydata.txt"},
    new AmpFile{filename="testfile1.jpg",actualpath="F:\\somefolder\\testfile1.jpg"},
    new AmpFile{filename="testfile2.jpg",actualpath="F:\\somefolder\\testfile2.jpg"},
    new AmpFile{filename="testfile3.jpg",actualpath="D:\\testfile3.jpg"},
};

2 - вызов groupBy и фильтрация с Where:

List<AmpFile> notDuplicatedAmpFiles = ampFiles.GroupBy(x => x.filename)
    .Where(x => x.Count() == 1)
    .SelectMany(x => x)
    .ToList();

3 - демонстрация:

foreach(AmpFile ampFile in notDuplicatedAmpFiles)
{
    Console.WriteLine($"fileName :{ampFile.filename}, actualPath :{ampFile.actualpath}");
}

4 - результат :

fileName :brickwall.jpg, actualPath :C:\testpath\brickwall.jpg
fileName :testfile2.jpg, actualPath :F:\somefolder\testfile2.jpg
fileName :testfile3.jpg, actualPath :D:\testfile3.jpg

Надеюсь, это поможет.

2 голосов
/ 03 мая 2020

Я бы предложил этот запрос:

var results =
    from a in list
    group a by a.filename into gas
    where !gas.Skip(1).Any()
    from ga in gas.Take(1)
    select ga;

Если вы начнете с этими данными:

var list = new List<AmpFile>()
{
    new AmpFile() { filename = "testfile1.jpg", actualpath = @"C:\testpath\testfile1.jpg" },
    new AmpFile() { filename = "brickwall.jpg", actualpath = @"C:\testpath\brickwall.jpg" },
    new AmpFile() { filename = "mydata.txt", actualpath = @"D:\mydata.txt" },
    new AmpFile() { filename = "testfile1.jpg", actualpath = @"E:\demo\testfile1.jpg" },
    new AmpFile() { filename = "mydata.txt", actualpath = @"F:\somefolder\mydata.txt" },
    new AmpFile() { filename = "testfile1.jpg", actualpath = @"F:\somefolder\testfile1.jpg" },
    new AmpFile() { filename = "testfile2.jpg", actualpath = @"F:\somefolder\testfile2.jpg" },
    new AmpFile() { filename = "testfile3.jpg", actualpath = @"D:\testfile3.jpg" },
};

... тогда вы получите такой результат:

results

1 голос
/ 03 мая 2020

Вы можете использовать IEquals как код ниже. Ваши пути находятся в разных папках, поэтому у вас нет дубликатов. Смотрите ниже:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<AmpFile> files = new List<AmpFile>() {
                new AmpFile() { filename = "testfile1.jpg", actualpath = @"C:\testpath\testfile1.jpg"}, 
                new AmpFile() { filename = "brickwall.jpg", actualpath = @"C:\testpath\brickwall.jpg"}, 
                new AmpFile() { filename = "mydata.txt", actualpath = @"D:\mydata.txt"}, 
                new AmpFile() { filename = "testfile1.jpg", actualpath = @"E:\demo\testfile1.jpg"}, 
                new AmpFile() { filename = "mydata.txt", actualpath = @"F:\somefolder\mydata.txt"}, 
                new AmpFile() { filename = "testfile1.jpg" , actualpath = @"F:\somefolder\testfile1.jpg"}, 
                new AmpFile() { filename = "testfile2.jpg" , actualpath = @"F:\somefolder\testfile2.jpg"}, 
                new AmpFile() { filename = "testfile3.jpg", actualpath = @"D:\testfile3.jpg"}
            };

            List<AmpFile> output = files.Distinct().ToList();
        }
    }
    public class AmpFile : IEquatable<AmpFile>
    {
        public string filename { get; set; }
        public string actualpath { get; set; }

        public Boolean Equals(AmpFile other)
        {
            return ((this.filename == other.filename) && (this.actualpath == other.actualpath));
        }
        public override int GetHashCode()
        {
            return (this.filename + "^" + this.actualpath).GetHashCode();
        }
    }
}
0 голосов
/ 03 мая 2020
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
public class AmpFile
{
    public string filename { get; set; }
    public string actualpath { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        List<AmpFile> lstemail = new List<AmpFile>();
        lstemail.Add(new AmpFile { filename = "testfile1.jpg", actualpath= "C:\testpath\testfile1.jpg"});
        lstemail.Add(new AmpFile { filename = "brickwall.jpg", actualpath = "C:\testpath\brickwall.jpg" });
        lstemail.Add(new AmpFile { filename = "mydata.txt", actualpath = @"D:\mydata.txt" });
        lstemail.Add(new AmpFile { filename = "testfile1.jpg", actualpath = @"E:\demo\testfile1.jpg" });

        var myDistinctList = lstemail.GroupBy(i => 
   i.filename).Select(g => g.First()).ToList();
     lstemail = myDistinctList;

    }
}
}

Я использовал linq лучше, чем foreach.

0 голосов
/ 03 мая 2020

Запуск двух циклов в вашем списке - самый быстрый способ.

List<AmpFile> ampList = new List<AmpFile>();
// Populate list

for (int i = 0; i < ampList.Count; i++)
    for (int j = i + 1; j < ampList.Count; j++)
        if (ampList[j].filename == ampList[i].filename)
            ampList.RemoveAt(j);
0 голосов
/ 03 мая 2020

Если вам не нужно получать новый список вместо удаления из исходного списка, вы можете сделать это следующим образом (извините за сложность, я думаю, его можно легко оптимизировать → добавление разрывов и т. Д.):

List<AmpFile> foo(List<AmpFile> files)
{
 List<AmpFile> result = new List<AmpFile>();
 bool add = false;
 foreach(AmpFile file in files)
 {
  add = true;
  foreach(AmpFile alreadyAdded in result)
  {
   if(file.filename == alreadyAdded.filename)
   {
    add = false;
   }
  }
  if(add)
  {
   result.Add(file);
  }
 }
 return result;
}

Если вам действительно нужно изменить исходный список, вы можете сделать что-то вроде этого (можно снова оптимизировать):

void foo2(List<AmpFile> files)
{
 AmpFile[] temp = files.ToArray();
 List<AmpFile> toDelete = new List<AmpFile>();
 foreach(AmpFile file in temp)
 {
  foreach(AmpFile f in files)
  {
   if(f != file && f.filename == file.filename)
   {
    if(!toDelete.Contains(f))
    {
     toDelete.Add(f);
    }
   }
  }
 }

 foreach(AmpFile file in toDelete)
 {
   files.Remove(file);
 }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...