遍历列表,查找要合并到新列表中的类似项目

本文关键字:列表 项目 新列表 查找 合并 遍历 | 更新日期: 2023-09-27 18:35:11

这应该很容易做到,但我似乎无法理解它。 我有一个包含发件人、收件人、订单号和商品编号的商品列表。 我循环访问此列表以创建视图模型。 我需要合并具有相同托运人/收件人的商品。

这是我视图的代码:

// GET: /Hazmat/Pending
public ActionResult Pending()
{
    PendingViewModel pendingViewModel = new PendingViewModel();
    // Check for shipments created manually pending shipping
    List<HazmatInfo> pending = hazmatRepository.GetHazmatPendingShipping().ToList();
    List<PendingReceiver> pendingReceivers = new List<PendingReceiver>();
    List<HazmatLocation> shippers = new List<HazmatLocation>();
    PendingReceiver pendingReceiver = new PendingReceiver();
    List<PendingItem> pendingItems = new List<PendingItem>();
    foreach (HazmatInfo item in pending)
    {
        PendingReceiver tempReceiver = new PendingReceiver();
        List<PendingItem> tempItems = new List<PendingItem>();
        tempReceiver.Receiver = hazmatRepository.GetLocationById(item.ToBU);
        tempReceiver.Shipper = hazmatRepository.GetLocationById(item.FromBU);
        tempItems.Add(hazmatRepository.convertToPendingItem(hazmatRepository.GetItem(item.InvItemID), item.OrderNo, item.ToBU));
        tempReceiver.PendingItems = tempItems;
        pendingReceivers.Add(tempReceiver);
    }
    pendingReceivers = ConsolidateItems(pendingReceivers);
    pendingViewModel.PendingReceivers = pendingReceivers;
    //To get a distinct result, group by first found items
    foreach (HazmatInfo item in pending.GroupBy(s => s.FromBU).Select(grp => grp.First()))
    {
        HazmatLocation shipper = new HazmatLocation();
        shipper = hazmatRepository.GetLocationById(item.FromBU);
        shippers.Add(shipper);
    }
    pendingViewModel.Shippers = shippers;
    ViewBag.PendingCount = pending.Count();
    return View("Pending", pendingViewModel);
}

以下是合并我的项目的代码:

private List<PendingReceiver> ConsolidateItems(List<PendingReceiver> pendingReceivers)
{
    var groups = pendingReceivers.GroupBy(x => new { x.Shipper, x.Receiver });
    pendingReceivers = pendingReceivers.OrderBy(s => s.Receiver.Location).ToList();
    List<PendingReceiver> tempReceivers = new List<PendingReceiver>();
    tempReceivers = pendingReceivers.ToList();
    List<PendingItem> tempItems = new List<PendingItem>();
    int i = 0;
    foreach (PendingReceiver tempReceiver in pendingReceivers)
    {
        while (i < pendingReceivers.Count - 1)
        {
            if ((pendingReceivers[i].Receiver.Location == pendingReceivers[i + 1].Receiver.Location) &&
                (pendingReceivers[i].Shipper.Location == pendingReceivers[i + 1].Shipper.Location))
            {
                if (tempItems.Count == 1)
                {
                    tempItems.Add(pendingReceivers[i + 1].PendingItems.SingleOrDefault());
                }
                tempItems.Add(pendingReceivers[i].PendingItems.SingleOrDefault());
                tempReceivers[i].PendingItems = tempItems;
                tempReceivers.RemoveAt(i + 1);
            }
            i++;
        }
    }
    return tempReceivers;
}

这是我的 PendingReceivers 类:

using System.Collections.Generic;
using System.Collections;
namespace Hazmat.Models
{
    public class PendingReceiver : IEnumerable
    {
        public HazmatLocation Receiver { get; set; }
        public HazmatLocation Shipper { get; set; }
        public IEnumerable<PendingItem> PendingItems { get; set; }
        public IEnumerator GetEnumerator()
        {
            yield return this.PendingItems;
        }
    }
}

我可以想象我需要做什么,但似乎无法实现它。

我已经编辑了我的合并项目方法...并添加了更多信息,例如我用来帮助解决此问题的数据......

目前,我的合并项目方法似乎有效,但跳过了一个项目(FromBu=02,ToBu=10)。

鉴于此数据:

ID

订单编号 项目ID 类型 数量 从BU ToBU

4055 370047528 850265手册 12.0000 24 01

4069 996564490 582526手册 1.0000 02 10

4070 996564491 940145手册 2.0000 70 49

4071 996564492 430051手册 3.0000 24 60

4072 996564493 851110 手册 1.0000 02 01

4073 996564493 173000 手册 10.0000 02 01

4075 996564493 928002手册 1.0000 02 01

此列表中的最后 3 项应为 PendingReceivers.PendingItems 中的 3 项。 我的初始查询将上述数据从我的数据库中提取出来。 我需要从这些数据构建我的模型。 PendingReceiver.Receiver 包含我的收件人数据,PendingReceiver.Shipper 包含我的收件人数据。 我可能也想多了...

谢谢

提姆

遍历列表,查找要合并到新列表中的类似项目

您需要对具有相同ShipperReceiver的项目进行分组?您可以使用 LINQ 执行此操作

var groups = _pendingReceivers.GroupBy(x => new { x.Shipper, x.Receiver });

这将为您提供一个IGrouping<TKey, PendingReceiver>,其中TKey是由ShipperReceiver组成的匿名类型。然后,您可以使用这些组输出到List 中。

// Flatten the groups into a single list
var consolidated = groups.SelectMany(e => e);

在这里,看看这是否有效:

private List<PendingReceiver> ConsolidateItems(List<PendingReceiver> _pendingReceivers)
{
    return _pendingReceivers
        .GroupBy(x => new { x.Shipper, x.Receiver })
        .SelectMany(e => e)
        .ToList();
}

假设您已正确覆盖HazmatLocation.Equals,上述方法应该可以工作。

欢迎使用堆栈溢出:)

这似乎是 Linq 的一个出色用例,更具体地说,是 GroupBy 方法。

查看此文章以获取更多信息

你可以试试这个DistinctBy 扩展方法(归功于 Jon Skeet):

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
                            this IEnumerable<TSource> source
                             , Func<TSource, TKey> selector)
{
    var set = new HashSet<TKey>();
    return source.Where(element => set.Add(selector(element)));
}
pendingReceivers = pendingReceivers.DistinctBy( pr => new { pr.Shipper
                                                          , pr.Receiver });

您还需要在 ShipperReceiver 类上实现IEqualityComparer - http://msdn.microsoft.com/en-us/library/ms132151.aspx

我能够回到我正在执行原始查询的位置,并找到一个 LINQ 语句,该语句立即为我提供了我需要的东西,而不是试图在事后将结果扭曲到我的意愿...... 感谢我今天早上刚刚发现的 LINQPad 的帮助。

HazmatInfo.Where (h => (h.ShippingFlag.Equals("false") && h.ShippingType.Equals("Manual")))).GroupBy(x => new { x.ToBU, x.FromBU }, y => new { y }).Distinct()

提姆