2013-07-12 121 views
3

應用程序的一些背景。這是針對我擁有的WASP和SMPP發射器帳戶。LINQ/Lambda更新通過將項目拆分成偶數組來列出項目

我有一個列表<>它包含一個對象,該對象具有SMPP PDU的所有必需對象併發送消息。 此列表包含名爲「路由標籤」的屬性,路由標籤將指示哪個服務提供商將PDU提交給(Vodacom,MTN,Cell C)。

我有另一個帳戶列表,我可以綁定到SMPP服務器併發送消息。該列表還包含路由標籤並且具有發射器帳戶的名稱。因此,例如Vodacom的路由標籤是「D082」,我有兩個帳戶可以同時綁定。

我現在需要採取第一個清單<>並更新字段。可以說第一個列表<>有1000個項目。我需要將這些(或多或少均勻地)分配給我提到的第二個列表<>中出現的每個「路由標籤」的所有帳戶。

我寧願使用linq或lambda來實現所需的功能。

=====編輯:添加代碼示例,以便您善良的人可以幫助我:-)對不起,標準很差,但我快速剝離了一些代碼給你們。我希望這有助於我的問題。

static void Main(string[] args) 
    { 


     List<MobileAccounts> TransmitterAccounts = new List<MobileAccounts>();//This list contains my transmitter accounts 


     MobileAccounts item = new MobileAccounts(); 
     item.FriendlyName = "Vodacom 1"; 
     item.RoutingLabel = "D082"; 
     TransmitterAccounts.Add(item); 

     MobileAccounts item1 = new MobileAccounts(); 
     item1.FriendlyName = "Vodacom 2"; 
     item1.RoutingLabel = "D082"; 
     TransmitterAccounts.Add(item1); 


     MobileAccounts item2 = new MobileAccounts(); 
     item2.FriendlyName = "MTN 1"; 
     item2.RoutingLabel = "D083"; 
     TransmitterAccounts.Add(item2); 


     MobileAccounts item3 = new MobileAccounts(); 
     item3.FriendlyName = "MTN 2"; 
     item3.RoutingLabel = "D083"; 
     TransmitterAccounts.Add(item3); 

     MobileAccounts item4 = new MobileAccounts(); 
     item4.FriendlyName = "MTN 3"; 
     item4.RoutingLabel = "D083"; 
     TransmitterAccounts.Add(item4); 

     MobileAccounts item5 = new MobileAccounts(); 
     item5.FriendlyName = "CellC 1"; 
     item5.RoutingLabel = "D084"; 
     TransmitterAccounts.Add(item5); 

     MobileAccounts item6 = new MobileAccounts(); 
     item6.FriendlyName = "CellC 2"; 
     item6.RoutingLabel = "D084"; 
     TransmitterAccounts.Add(item6); 


     List<SubmitSm> col = new List<SubmitSm>();//this list contains messages in a queue ready for sending 

     SubmitSm sitem = new SubmitSm(); 
     sitem.DestAddr = "0722222222";//Vodacom number 
     sitem.RoutingLabel = "D082"; 
     col.Add(sitem); 

     SubmitSm sitem1 = new SubmitSm(); 
     sitem1.DestAddr = "0722222220";//Vodacom number 
     sitem1.RoutingLabel = "D082"; 
     col.Add(sitem1); 

     SubmitSm sitem2 = new SubmitSm(); 
     sitem2.DestAddr = "0722221212";//Vodacom number 
     sitem2.RoutingLabel = "D082"; 
     col.Add(sitem2); 

     SubmitSm sitem3 = new SubmitSm(); 
     sitem3.DestAddr = "0830000000";//MTN number 
     sitem3.RoutingLabel = "D083"; 
     col.Add(sitem3); 


     SubmitSm sitem4 = new SubmitSm(); 
     sitem4.DestAddr = "0833746005";//MTN number 
     sitem4.RoutingLabel = "D083"; 
     col.Add(sitem4); 

     SubmitSm sitem5 = new SubmitSm(); 
     sitem5.DestAddr = "0749999998";//CellC number 
     sitem5.RoutingLabel = "D084"; 
     col.Add(sitem5); 

     /* 
     * Now this is where I will need 
     * to split all the messages in "col" 
     * amongst all the transmitter accounts 
     * I have. 
     */ 


    } 

public class MobileAccounts 
{ 
    /*Please note not all items 
    are in this class. I have 
    * removed some as they are not 
    * neccessary for this demo code.    
    */ 

    //[DataMember] 
    public string FriendlyName; 

    //[DataMember] 
    public string BindName; 

    //[DataMember] 
    public string BindPassword; 

    //[DataMember] 
    public string BindHost; 

    //[DataMember] 
    public string BindPort; 

    //[DataMember] 
    public string BindType; 

    //[DataMember] 
    public string ProviderCode; 

    //[DataMember] 
    public string RoutingLabel; 


} 

public class SubmitSm 
{ 
    /*Please note not all items 
    are in this class. I have 
    * removed some as they are not 
    * neccessary for this demo code.    
    */ 
    public byte DefaultMessageId { get; set; } 

    public string DestAddr { get; set; } 

    public byte DestAddrNpi { get; set; } 

    public byte DestAddrTon { get; set; } 

    public string MessageText { get; set; }   

    public byte PriorityFlag { get; set; } 

    public byte ProtocolId { get; set; } 

    public byte RegisteredDelivery { get; set; }     

    public string ScheduleDeliveryTime { get; set; } 

    public string ServiceType { get; set; } 

    public string SourceAddr { get; set; } 

    public byte SourceAddrNpi { get; set; } 

    public byte SourceAddrTon { get; set; } 

    public string ValidityPeriod { get; set; } 

    public string RoutingLabel { get; set; } 

} 

謝謝大家的貢獻。 @NinjaNye你的解決方案很近,但並不完全符合我的要求。儘管如此,我很欣賞你的努力。

認爲我幾乎在那裏,但我掙扎。有人可以幫助我找出如下所示的子選擇:

List<IGrouping<string, MobileAccounts>> sad1 = TransmitterAccounts.GroupBy(y => y.RoutingLabel).ToList(); 
col = (List<SubmitSm>)col.Select 
           (x => 
            { 
             x.ServiceType = sad1.Where 
                   (z => 
                    z.Key==  x.ServiceType 
                     )              
                     .Select 
                      (y => 
                        new 
                        { 
                         //this should return the Transmitter account that has the lowest count 

                         TransmitterAccount = y.OrderBy(ui => x.ServiceType.Count()).Select(ui => ui.FriendlyName).First() 
                        } 
                      ).First().TransmitterAccount;             

               return x; 
             } 
            ).ToList(); 
+0

歡迎來到Stack Overflow!雖然我確信可以用一些背景來理解你的問題,但是很難看到相關的代碼。看起來您在這裏有兩種自定義類型 - 要傳輸的項目以及路由信息。顯示這些類的相關屬性將有所幫助。這也有助於查看您編寫的代碼來嘗試自己解決此問題 - 修復別人的代碼通常比從頭開始編寫新代碼更容易。 – dasblinkenlight

+0

問題很簡單,我有一堆去不同商店的水果。我有一堆商店,每個商店都有幾個籃子。我想將每個商店指定的水果均勻分​​配到籃子之間。然而,答案並不是那麼容易......在這個問題上工作,但也許有人比我更聰明會先到達那裏:p –

+0

@DaveWilliams:哈哈哈!!!今天早上你的評論使我的臉上露出了微笑。但是,戴夫,你是100%正確的。我希望上面的代碼會有幫助。 – BossRoss

回答

2

唯一使用LINQ的,我可以看到這裏可能是使用的.Skip().Take()但是我已經創建了一個擴展方法來整理了一點東西。這意味着你可以簡單地寫下面的內容來拆分任何IEnumerable

// In your example above you need to replace `items` with your `col` variable 
var result = items.Split(transmitter.Count()); 

擴展方法

http://www.ninjanye.co.uk/2013/07/splitting-distributing-list-objects.html

http://jnye.co/Posts/10/evenly-splitting-distributing-a-list-of-objects-using-linq-and-extension-methods

public static class EnumerableExtensions 
{ 
    public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int groups) 
    { 
     var listedSource = source.ToList(); 
     int extra; 
     int groupSize = Math.DivRem(listedSource.Count(), groups, out extra); 

     while (listedSource.Any()) 
     { 
      int newSize = groupSize; 
      if (extra > 0) 
      { 
       newSize++; 
       extra--; 
      } 
      yield return listedSource.Take(newSize); 
      listedSource = listedSource.Skip(newSize).ToList(); 
     } 
    } 
} 

結果

我設置此起來作爲一個快速的命令程序來測試

這裏有一些成果,所以你可以看到項目拆分: Example output of splitting

戰後初期(現上述重構)

像這樣的東西應該做的它...不過我已經簡化的例子

 // This is your transmitter count 
     int groups = 4; 
     // These are your SMS's 
     List<int> values = new List<int>(){1,2,3,4,5,6,7,8,9}; 

     //Calculate group size 
     int extra; 
     int groupSize = Math.DivRem(values.Count, groups, out extra); 

     var result = new List<IEnumerable<int>>(); 
     while (values.Any()) 
     { 
      int newSize = groupSize; 
      if (extra > 0) 
      { 
       // Account for extras 
       newSize++; 
       extra--; 
      } 
      result.Add(values.Take(newSize)); 
      values = values.Skip(newSize).ToList(); 
     } 

     return result; 

-1

你應該避免帶有副作用的LINQ。但是你可以將對象附加到列表中。

 List<MobileAccounts> mas = new List<MobileAccounts>(); 
     List<SubmitSm> sms = new List<SubmitSm>(); 

     var result = mas.Select(ma => new {Sm=(sms.First(sm => sm.RoutingLabel == ma.RoutingLabel)),Ma=ma}); 
     foreach (var r in result) 
     { 
      //update Properties here 
     }