1

我想要做的是在 searchValues 列表中搜索重复的 itemId,当我找到它们时,将单个字符串值放入字符串值数组中。

SearchValue 对象:

public class SearchValue<TItemId>
{
    public TItemId ItemId { get; set; }
    public string Value { get; set; }
    public string[] Values { get; set; }
}

init 后我的测试搜索值如下所示:

   searchValues[0]
        .ItemId == 16
        .Value == "2"
    searchValues[1]
        .ItemId == 16
        .Value == "3"
    searchValues[2]
        .ItemId == 15
        .Value == "6"
    searchValues[3]
        .ItemId == 15
        .Value == "3"
    searchValues[4]
        .ItemId == 5
        .Value == "Vertonghen"

我希望我的最终结果如下所示:

searchValues[0]
    .ItemId == 16
    .Values == "2,3"
searchValues[1]
    .ItemId == 15
    .Values == "6,3"
searchValues[2]
    .ItemId == 5
    .Value == "Vertonghen"

我真的很想使用 LINQ 来做到这一点。因此,我设法创建了另一个 SearchValue 列表:

List<SearchValue<Byte>> duplicateSearchItems = (from x in searchValues
                                 group x by x.ItemId into grps
                                 orderby grps.Key
                                 where grps.Count() > 1
                                 select grps).SelectMany(group => group).ToList();

...但是将值放入 values 数组给我带来了麻烦。理想情况下,如果 LINQ 可以返回一个包含重复记录的列表,该列表包含被变形到数组中的重复记录,且非重复项完整无缺。可能是某种嵌套查询?我难住了。有任何想法吗?

提前致谢!

4

4 回答 4

0

你为什么不使用字典

    Dictionary<int,string> d = new Dictionary<int,string>();
    foreach(var x in searchValues)
    {
        if(d.ContainsKey(x.ItemId))
           d[x.ItemId] = string.Format("{0},{1}",d[x.ItemId],x.Value);
        else
           d.Add(x.ItemId,x.Value);
    }

最后简单地遍历字典

    foreach(var entry in d)
    {
       ConsoleWriteline(entry.Key+" : "+entry.Value);
    }
于 2013-05-31T18:44:46.427 回答
0

不能单独使用 Linq 来修改原始列表或修改列表中的项目。但是,您可以这样做来创建一个新列表:

List<SearchValue<Byte>> results = 
    (from x in searchValues
     group x by x.ItemId into g
     select new SearchValue<Byte>()
     {
         ItemId = g.Key,
         Value = g.Value.First().Value,
         Values = g.Value.Select(i => i.Value).ToArray(),
     }
    .ToList();

或流利的语法:

List<SearchValue<Byte>> results = searchValues
    .GroupBy(x => x.ItemId)
    .Select(g => new SearchValue<Byte>()
            {
                ItemId = g.Key,
                Value = g.Value.First().Value,
                Values = g.Value.Select(i => i.Value).ToArray(),
            })
   .ToList();

但是,根据您的情况,ILookup可能更适合您:

var results = searchValues.ToLookup(x => x.ItemId, x => x.Value);
Console.Write(String.Join(", ", results[16])); // 2, 16
于 2013-05-31T18:47:05.067 回答
0

我认为 LINQ 不会在这里为您提供最佳解决方案。与 Nikola 类似,我会使用字典。如果您没有与您的 SearchValue 数据类型结婚,您可以避免第二个循环,该循环只是将您的数据推回您的类型。Dictionary> 在这里可以工作。

            var searchValues = new List<SearchValue<int>>();
            var distinctItemIds = new Dictionary<int, List<string>>();

            foreach (var item in searchValues)
            {
                if (!distinctItemIds.ContainsKey(item.ItemId))
                {
                    distinctItemIds.Add(item.ItemId, new List<string>());
                }

                // Add the value
                distinctItemIds[item.ItemId].Add(item.Value);
            }

            // Put values back into your data object
            var finishedValues = new List<SearchValue<int>>();

            foreach (var keyValuePair in distinctItemIds)
            {
                finishedValues.Add(new SearchValue<int>()
                {
                    ItemId = keyValuePair.Key,
                    Values = keyValuePair.Value.ToArray()
                });
            }
于 2013-05-31T19:40:15.107 回答
0

我设法使用 LINQ 解决了这个问题。

// Get a new list of unique items to add our duplicated items to
List<SearchValue<Byte>> finalSearchItems = (from x in searchValues
                            group x by x.ItemId into grps
                            orderby grps.Key
                            where grps.Count() == 1
                            select grps).SelectMany(group => group).ToList();

byte[] duplicateIds = (from x in searchValues
             group x by x.ItemId into grps
             where grps.Count() > 1
             select grps.Key).ToArray();

// Smash the string 'Value' into 'Values[]'
foreach (byte id in duplicateIds)
{
    SearchValue<Byte> val = new SearchValue<byte>();
    val.ItemId = id;
    // Smash
    val.Values = (from s in searchValues
              where s.ItemId == id
              select s.Value).ToArray();
    finalSearchItems.Add(val);
}
于 2013-06-03T02:06:37.933 回答