Не только получать дубликаты из массива, но также нужен индекс дубликатов - PullRequest
0 голосов
/ 15 июля 2011

У меня есть следующий массив:

Driver[] predictions = new Driver[6];
predictions[0] = new Driver(10, "Michael Schumacher");
predictions[1] = new Driver(10, "Michael Schumacher");
predictions[2] = new Driver(9, "Fernando Alonso");
predictions[3] = new Driver(8, "Jensen Button");
predictions[4] = new Driver(7, "Felipe Massa");
predictions[5] = new Driver(6, "Giancarlo Fisichella");

Я хочу получить все дубликаты - имя один раз, а затем позиции (указатели), где находятся дубликаты. Итак, в этом случае я хочу получить «Михаэля Шумахера» и позиции 1 и 2 (индекс 0 и 1).

Можно ли это сделать за один раз, или мне нужно рассмотреть другие варианты? Я только что прочитал на DotNetPearls, что IndexOf довольно медленный по сравнению с вашей собственной логикой.

var driversSelectedMoreThanOnceAndTheirPositions = predictions.Select((driver, index) => new { driver, index })
.GroupBy(item => item.driver.Name)
.Where(grp => grp.Count() > 1)
.ToDictionary(g => g.Key, g => g.Select(a => (a.index + 1)).ToList());

Ответы [ 3 ]

1 голос
/ 15 июля 2011

Чтобы использовать для этого linq, вы могли бы написать что-то вроде следующего, которое использует перегрузку Select, которая позволяет получить индекс элемента, а затем выполняет операцию GroupBy.

var query = 
 predictions.Select((driver, index) => new { driver, index })
 .GroupBy(item => item.driver.Name)
 .Where(grp => grp.Count() > 1)
 .Select(grp => new { Name = grp.Key, Indexes = grp.Select(item => item.index) });

Это приведет к последовательности объектов анонимного типа со свойствами

class Anon
{
    public string Name;
    public IEnumerable<int> Indexes;
}

, которые вы можете использовать, как в

foreach (var item in query)
{
    Console.WriteLine(item.Name);
    foreach (int index in item.Indexes)
        Console.WriteLine(index);
}

Конечно, вы можете изменить способ группировкичтобы получить весь объект драйвера.

0 голосов
/ 15 июля 2011

Учитывая очевидное определение класса Driver, это должно дать вам то, что вы хотите:

        Driver[] predictions = new Driver[6];
        predictions[0] = new Driver(10, "Michael Schumacher");
        predictions[1] = new Driver(10, "Michael Schumacher");
        predictions[2] = new Driver(9, "Fernando Alonso");
        predictions[3] = new Driver(8, "Jensen Button");
        predictions[4] = new Driver(7, "Felipe Massa");
        predictions[5] = new Driver(6, "Giancarlo Fisichella");

        var ds = predictions.Select((driver, i) => new { Name = driver.Name, Index = i })
                            .GroupBy(a => a.Name, a => a.Index);
0 голосов
/ 15 июля 2011

Приведенный ниже код даст вам словарь с ключом по имени водителя со значением всех их позиций в исходном массиве.Он также предоставит вам уникальный список (HashSet), содержащий только те имена драйверов, которые встречались в оригинальном массиве более одного раза.

      Driver[] predictions = new Driver[6];
      predictions[0] = new Driver(10, "Michael Schumacher");
      predictions[1] = new Driver(10, "Michael Schumacher");
      predictions[2] = new Driver(9, "Fernando Alonso");
      predictions[3] = new Driver(8, "Jensen Button");
      predictions[4] = new Driver(7, "Felipe Massa");
      predictions[5] = new Driver(6, "Giancarlo Fisichella");

      Dictionary<string, List<int>> indicies = new Dictionary<string, List<int>>();
      HashSet<string> driversWithDups = new HashSet<string>();
      for (int i=0; i<predictions.Length; i++)
      {
        Driver eachDriver = predictions[i];
        if (indicies.ContainsKey(eachDriver.Name))
        {
          indicies[eachDriver.Name].Add(i);
          driversWithDups.Add(eachDriver.Name);
        }
        else
        {
          indicies[eachDriver.Name] = new List<int>() {i};
        }
      }
...