1

这应该很容易做到,但我似乎无法理解它。我有一个包含发货人、收件人、订单号和项目 ID 的项目列表。我遍历这个列表来为视图创建我的模型。我需要合并具有相同发货人/收货人的物品。

这是我的视图的代码:

// 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;
        }
    }
}

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

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

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

鉴于此数据:

ID OrderNo ItemID Type Qty FromBU 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 我的托运人数据。这个我可能也想多了。。。

谢谢,

蒂姆

4

4 回答 4

2

您需要对具有相同Shipper和的项目进行分组Receiver?你可以用 LINQ 做到这一点

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

这将为您提供由和组成的匿名类型在IGrouping<TKey, PendingReceiver>哪里。然后,您可以使用这些组输出到.TKeyShipperReceiverList

// 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,上述内容应该可以工作。

于 2013-10-11T19:51:07.143 回答
1

欢迎来到堆栈溢出 :)

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

查看这篇文章了解更多信息

于 2013-10-11T19:50:23.870 回答
0

您可以尝试这种 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 });

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

于 2013-10-11T19:54:46.263 回答
0

我能够后退一步,回到原来的查询,并找到了一个 LINQ 语句,它立即为我提供了我需要的东西,而不是事后试图将结果扭曲成我的意愿......谢谢在我今天早上刚刚发现的 LINQPad 的帮助下。

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

蒂姆

于 2013-10-16T16:00:40.197 回答