如何获取列表中重复项的值和索引?

时间:2013-03-18 18:20:10

标签: c# list duplicates

我有一个文件名列表(targetFileList),其中一些是重复的(例如,我有两个名为m4.txt的文件)。以下语句查找重复的文件名,并将它们添加到另一个列表(currentTargetFiles):

currentTargetFiles = targetFileList.FindAll(item => item == baselineFilename);

原样,这一行返回一个字符串列表(文件名),这很好,但我也需要它们的索引值。有没有办法修改它,以便它还返回文件的索引?

4 个答案:

答案 0 :(得分:7)

嗯,这是我找到“找到重复的名称及其索引”的答案。它可能不完全符合所提出的问题,因为没有考虑baselineFilename - 但其他答案也涵盖了这一点。 YMMV。

var names = new [] {"a", "a", "c", "b", "a", "b"};

var duplicatesWithIndices = names
    // Associate each name/value with an index
    .Select((Name, Index) => new { Name, Index })
    // Group according to name
    .GroupBy(x => x.Name)
    // Only care about Name -> {Index1, Index2, ..}
    .Select(xg => new {
        Name = xg.Key,
        Indices = xg.Select(x => x.Index)
    })
    // And groups with more than one index represent a duplicate key
    .Where(x => x.Indices.Count() > 1);

// Now, duplicatesWithIndices is typed like:
//   IEnumerable<{Name:string,Indices:IEnumerable<int>}>

// Let's say we print out the duplicates (the ToArray is for .NET 3.5):
foreach (var g in duplicatesWithIndices) {
    Console.WriteLine("Have duplicate " + g.Name + " with indices " +
        string.Join(",", g.Indices.ToArray()));
}

// The output for the above input is:
// > Have duplicate a with indices 0,1,4
// > Have duplicate b with indices 3,5

当然,提供的结果必须正确使用 - 这取决于最终必须做什么。

答案 1 :(得分:2)

int i = -1;
var currentTargetFiles = targetFileList.Select(x => new
                                                        {
                                                           Value = x,
                                                           Index = i++
                                                        })
                                       .Where(x => x.Value == baselineFilename);

答案 2 :(得分:2)

您可以选择带有索引的所有项目:

tempList = targetFileList.Select((item, index) => 
    new { Value = item, Index = index }).Where(x => x.Value == baselineFilename);

现在,您可以使用以下命令创建名称和相应索引的列表:

var indexes = tempList.Select(x => x.Index).ToList();

价值观:

currentTargetFiles = tempList.Select(x => x.Value).ToList();

然后,indexes[0]将保留currentTargetFiles[0]的列表索引。

答案 3 :(得分:1)

linq是否需要?

传统的for循环和字典会很好:

Dictionary<int, string> currentTargetFiles = new Dictionary<int, string>();
for (int i = 0; i < targetFileList.Count; ++i)
    if(targetFileList[i] == baselineFilename)
        currentTargetFiles.Add(i, targetFileList[i]);

P.S:

刚才意识到你要比较一个确切的字符串(item == baselineFilename)。

如果是这种情况,您甚至不需要为每个索引保留每个值(因为所有值都相同)。

List<int> currentTargetFilesIndices = new List<int>();
for (int i = 0; i < targetFileList.Count; ++i)
    if(targetFileList[i] == baselineFilename)
        currentTargetFiles.Add(i);