LINQ GroupBy return 列表作为结果

LINQ GroupBy return List as result

我有一个包含事务对象的列表。我想要做的是在上述列表中找到具有相同 transaction.Buyer.UserID 的交易,并将它们组合成一个列表列表。

每个子列表项目将包含多个交易对象,其中 transaction.Buyer.UserID 相同。

我目前拥有的是:

            var _ordersToCombine = 
            _transactions.GroupBy(transaction => transaction.Buyer.UserID).Select(transaction => transaction);

我的收获:

List<Transaction>:
    Transaction { Buyer.UserID = "User1" ...}
    Transaction { Buyer.UserID = "User2" ...}
    Transaction { Buyer.UserID = "User1" ...}
    Transaction { Buyer.UserID = "User3" ...}
    Transaction { Buyer.UserID = "User4" ...}
    Transaction { Buyer.UserID = "User3" ...}

我对 return 的期望是:

List<List<Transaction>>:
    List<Transaction>:
        Transaction { Buyer.UserID = "User1" ...}
        Transaction { Buyer.UserID = "User1" ...}
    List<Transaction>:
        Transaction { Buyer.UserID = "User3" ...}
        Transaction { Buyer.UserID = "User3" ...}

...并从主列表中删除这些交易,因此在本例中主列表将如下所示:

List<Transaction>:
    Transaction { Buyer.UserID = "User2" ...}
    Transaction { Buyer.UserID = "User4" ...}

Linq 对我来说是一个新概念,我正在努力理解。

不,你得到的是 IEnumerable<IGrouping<TKey, TSource>> 请参阅:MSDN Group By

所以基本上它是 returns 组列表。该组包含对其进行分组的键和属于该组的项目列表的元素

列表

  • 第 1 组
    • 组键
    • 项目(您的对象列表)
  • 第 2 组
    • 组键
    • 项目(您的对象列表)

很好的解释:https://www.udemy.com/blog/linq-group-by/

试试这个:

var dic = _transactions.GroupBy(t => t.Buyer.UserID).ToDictionary(t => t.Key, t => t.ToList());

GroupBy returns一个

IEnumerable<IGrouping<TKey, TSource>>

每个 IGrouping<> 都包含组标准作为键,并且每个 IGrouping 都是可枚举的(您列出分组值)

因为,问题改变了:

不要在 GroupBy 委托中创建匿名类型(没有新的 {...}) 相反,直接针对 属性(因为在内部,GroupBy 使用相等性对事物进行分组,并且由于您创建了一个新的匿名对象,所以不会有任何分组,因为每个新对象都是不同的)

.GroupBy(o => o.Buyer.UserID, o.ToList) 

此外,

Select(p => p) 

什么都不做,这是一个身份函数。没用。

如果你想要的是List of List,我觉得你可以直接用Dictionary。 (请参阅我的回答的第一部分)您可以像枚举列表一样枚举字典。其中 add/remove/replace 项。

返回的字典类型为:

Dictionary<int,List<Transactions>> dic =....

使用 Key = UserId,并且对于每个键,一个交易列表。 此外,它确实比列表的列表更快,因为您可以直接访问交易:

int userId = 42;
List<Transactions> transactions = dic[userId];

Group by in LINQ.

这里有您的查询的答案。

var results = transactions.GroupBy(p => p.Buyer.UserID,
                         (key, g) => new { UserID = key, Cars = g.ToList() });

如果我没理解错的话,

您有一个交易清单, 和列表的交易列表。

你需要对后者进行分组, 通过 userId,其中值将是对应于该用户的交易。

如果是这样的话, 我准备了一个可能有用的小样本。

祝你好运

public class Transaction
{
    public Buyer Buyer { get; set; }
}

public class Buyer
{
    public int UserID { get; set; }
}


[TestMethod]
public void Test()
{

    var t1 = new Transaction { Buyer = new Buyer { UserID = 1 } };
    var t2 = new Transaction { Buyer = new Buyer { UserID = 2 } };
    var t3 = new Transaction { Buyer = new Buyer { UserID = 3 } };
    var t4 = new Transaction { Buyer = new Buyer { UserID = 1 } };
    var t5 = new Transaction { Buyer = new Buyer { UserID = 3 } };

    var tList1 = new List<Transaction> { t1, t2, t3 };
    var tList2 = new List<Transaction> { t4, t5 };

    var tLists = new List<List<Transaction>> { tList1 , tList2};

    var result = tLists.
        SelectMany(o => o).
        GroupBy(o =>  new 
        {
            UserId = o.Buyer.UserID
        },
        (key, items) => new
        {
            UserId = key.UserId,
            Transactions = items.Select(p => p).ToList()
        }).
        ToList();
}

这是作者编辑的更新解决方案:

    var transactions = new List<Transaction>
    {
        new Transaction { Buyer = new Buyer { UserID = 1 } },
        new Transaction { Buyer = new Buyer { UserID = 2 } },
        new Transaction { Buyer = new Buyer { UserID = 3 } },
        new Transaction { Buyer = new Buyer { UserID = 1 } },
        new Transaction { Buyer = new Buyer { UserID = 3 } }
    };

    var result = transactions.
        Select(o => o).
        GroupBy(o => new
        {
            UserId = o.Buyer.UserID
        },
        (key, items) => new
        {
            //UserId = key.UserId,
            Transactions = items.Select(p => p).ToList()
        }).
        ToList();

只需使用它进行分组:

var results = transactions
.GroupBy(p => p.Buyer.UserID)
.Where(x=>x.Count()>1)
.Select(x=> new List<Transaction>(x));

这应该会产生您的 List<List<Transaction> 以及来自主列表的重复用户。 LINQ 并不是在遍历集合时修改集合的真正正确工具。如果你真的需要它,请执行:

var results = transactions.ToList()
.GroupBy(p => p.Buyer.UserID)
.Where(x=>x.Count()>1)
.Select(x=> 
{
    foreach(var item in x)
        transactions.Remove(item);
    return new List<Transaction>(x);
});

请注意,已创建事务列表的副本以执行查询(transactions.ToList(),并在原始列表上进行删除操作。希望对您有所帮助。