在逗号分隔的字符串中查找重复条目的索引位置

时间:2013-11-29 01:41:29

标签: c# linq

我的问题比我想象的要复杂得多,我刚刚抹去了原来的问题......所以我可能会发布多个问题,具体取决于我是如何继续这样做的。

无论如何,回到问题。我需要在包含csv数据的字符串中找到重复条目的索引位置。例如,

FirstName,LastName,Address,Address,Address,City,PostCode,PostCode,Country

正如您所看到的,地址是重复的,我需要找出每个重复项的索引,假设第一个索引位置从0开始。

如果您对如何做到这一点有更好的建议,请告诉我,但假设可以这样做,我们是否可以使用dicitionary>?

因此,如果我必须对此进行编码,您将拥有:

duplicateIndexList.Add(2);
duplicateIndexList.Add(3);
duplicateIndexList.Add(4);

myDuplicateList.Add("Address", duplicateIndexList);

duplicateIndexList.Add(6);
duplicateIndexList.Add(7);

myDuplicateList.Add("PostCode", duplicateIndexList);

显然我不想这样做但是有可能使用Linq来实现上述目的吗?我可以编写一个可以实现此功能的功能,但我很高兴看到Linq可以做些什么。

如果您对我为什么要这样做感到好奇?好吧,简而言之,我有一个xml定义,用于将csv字段映射到数据库字段,我想首先找出是否有任何重复的列,然后我想要从实际的csv行追加相关值,即地址=地址(2)+地址(3)+地址(4),PostCode = PostCode(6)+ PostCode(7)

接下来的部分将是如何根据我添加实际值后找到的索引从上面定义的csv字符串中删除所有相关值,但这将是下一部分。

感谢。

吨。

UPDATE:

这是我想要的功能,但正如我所说,linq会很好。请注意,在此函数中,我使用的是列表而不是逗号分隔的字符串,因为我还没有将该列表转换为csv字符串。

Dictionary<string, List<int>> duplicateEntries = new Dictionary<string, List<int>>();

int indexPosition = 0;
foreach (string fieldName in Mapping.Select(m=>m.FieldName))
{
 string key = fieldName.ToUpper();
 if (duplicateEntries.ContainsKey(key))
   {
      List<int> indexes = duplicateEntries[fieldName];
      indexes.Add(indexPosition);
      duplicateEntries[key] = indexes;
      indexes = null;
   }
 else
   {
     duplicateEntries.Add(key, new List<int>() { indexPosition });
   }
 indexPosition += 1;
}

也许这有助于澄清我想要实现的目标。

2 个答案:

答案 0 :(得分:4)

您需要执行以下操作:

  1. 在结果数组上使用.Select投影新的IEnumerable个对象,其中包含数组中项目的索引以及值。
  2. 使用ToLookupGroupByToDictionary按列值对结果进行分组。
  3. 这似乎适合ILookup<string, int>

    var lookup = columnArray
        .Select((c, i) => new { Value = c, Index = i })
        .ToLookup(o => o.Value, o => o.Index);
    
    List<int> addressIndexes = lookup["Address"].ToList(); // 2, 3, 4
    

    或者如果您想创建Dictionary<string, List<int>>

    Dictionary<string, List<int>> dictionary = columnArray
        .Select((c, i) => new { Value = c, Index = i })
        .GroupBy(o => o.Value, o => o.Index)
        .ToDictionary(grp => grp.Key, grp => grp.ToList());
    
    List<int> addressIndexes = dictionary["Address"]; // 2, 3, 4
    

    修改

    (回应更新的问题)

    这应该有效:

    Dictionary<string, List<int>> duplicateEntries = Mapping
        .Select((m, i) => new { Value = m.FieldName, Index = i })
        .GroupBy(o => o.Value, o => o.Index)
        .ToDictionary(grp => grp.Key, grp => grp.ToList());
    

答案 1 :(得分:0)

您可以执行以下操作:

int count = 0;
var numbered_collection =
    from line in File.ReadAllLines("your_csv_name.csv").Skip(1)
    let parts = line.Split(',')
    select new CarClass()
    {
        Id = count++,
        First_Field = parts[0],
        Second_Field = parts[1], // rinse and repeat
    };

这会为每个项目提供Id。 (并且还跳过具有标题的第一行)。如果要将名称从第一个csv行自动映射到字段,可以将其放在方法中。

从那里,您可以:

var duplicates = (from items in numbered_collection
    group items by items.First_Field into g
    select g)
    .Where(g => g.Count() > 1);

现在您拥有实际上有重复项的所有组,您可以从对象中获取“Id”以了解哪个是重复的。