开发者

Not only get duplicates from array, but need as well index of the duplicates

I have the following array:

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");

I want to get all the duplicates - The name once, and then the positions (index) where the duplicates are. So, in this case I want to get "Michael Schumacher" and the positions 1 and 2 (index 0 and 1).

Can this be done in one go, or do I need to consider other options?开发者_开发知识库 I just read on DotNetPearls that IndexOf is pretty slow compared to having your own logic.

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());


To utilize linq for this, you could write something like the following, which uses an overload of Select that allows you to get the element index and then performs a GroupBy operation.

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

This will result in a sequence of anonymous-typed objects with the properties

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

Which you could use as in

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

You can, of course, change the way you group to get the entire driver object.


The code below will give you a dictionary keyed by driver's name, with a value of all their positions in the original array. It will also give you a unique list (HashSet) containing only those driver names which occurred more than once in the orginal array.

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


Given the obvious definition of the Driver class, this should give you what you want:

        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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜