【问题标题】:assigning random values from List<A> into List<B> C#将随机值从 List<A> 分配到 List<B> C#
【发布时间】:2018-10-30 15:06:48
【问题描述】:

我正在编写一个代码,将列表 A 中的随机数分配给列表 B 中的一组对象。

这里是要求:

我有一个活动列表和活动接收者列表,我需要涵盖三个场景:

  1. 当我在两个列表、2 个活动和 2 个收件人上的计数相同时“我对此完全没有问题,它会随机选择一个活动 ID 并将其分配给从列表 B 中随机选择的收件人,依此类推。
  2. 当我有 3 个活动和 1000 个收件人时,它会将收件人列表分为三组,并为每组分配一个随机选择的活动 ID。
  3. 当有 5 个活动和 3 个收件人时,它会随机选择 3 个活动并将它们分配给收件人。

我遇到的问题是第 2 点。这需要很长时间,以至于操作开始超时。它根据我的需要分配号码,但在处理 1k 或更多收件人时非常慢。

private static void RandomizeScenarios(ref IList<CampaignLib> cmp, ref IList<CampaignRecipientLib> rec)
{
    IEnumerable<int> RecipientsIds = rec.Select(x => x.ID).ToList();
    IList<int> CampaignsIds = cmp.Select(x => x.CampaignId.Value).ToList();
    int initVal = RecipientsIds.Count() / CampaignsIds.Count;
    int i = 0;

    if (CampaignsIds.Count < rec.Count())
    {
        List<CampaignRecipientLib> tmpRecipients = new List<CampaignRecipientLib>();

        foreach (var item in CampaignsIds)
        {
            i++;
            IEnumerable<int> tmp = null;

            if (i < CampaignsIds.Count) tmp = RecipientsIds.Shuffle().Take(initVal);
            else tmp = RecipientsIds.Shuffle().Take(RecipientsIds.Count());


            RecipientsIds = from r in RecipientsIds where !tmp.Contains(r) select r;

            var PartialRecipients = from r in rec where tmp.Contains(r.ID) select r;


            // HERE IT TAKES A VERY LONG TIME < 35mins for 2.5K objects
            PartialRecipients.ToList().ForEach(r => r.CampaignId = item);

            tmpRecipients.AddRange(PartialRecipients);

        }
        rec = tmpRecipients;
    }
    else if (CampaignsIds.Count == rec.Count())
    {
        foreach (var item in CampaignsIds)
        {
            int tmp = RecipientsIds.Shuffle().Take(1).FirstOrDefault();

            RecipientsIds = from r in RecipientsIds where tmp != r select r;

            rec.FirstOrDefault(x => x.ID == tmp).CampaignId = item;                  
        }
    }
    else if (CampaignsIds.Count > rec.Count())
    {
        foreach (var item in CampaignsIds.PickRandom(RecipientsIds.Count()).OrderBy(x => x))
        {
            int tmp = RecipientsIds.Shuffle().PickRandom(1).FirstOrDefault();

            RecipientsIds = from r in RecipientsIds where tmp != r select r;

            rec.FirstOrDefault(x => x.ID.Equals(tmp)).CampaignId = item;
        }
    }

}

【问题讨论】:

  • @Servy 正如我在帖子中提到的,第 2 点需要很长时间,有时会超时
  • 您不应该使用引号来提问。您应该使用引号来实际引用事物。
  • @Servy 好的注意,我是stackoverflow的新手,如果有任何有用的建议,让我们专注于这个问题,提前谢谢
  • 你对 Shuffle 的实现是什么?是否懒惰评估,如果是这样,您可能会发现每次执行tmp.Contains 时都在洗牌。如果是这样的话,一个 ToList(或者甚至更好地将它放在一个 HashSet 中)可以解决你的问题。

标签: c# linq random


【解决方案1】:

你把它弄得太复杂了。你可以这样做:

  • 随机排列收件人列表。
  • 第一个(nr 个收件人/广告系列计数)收件人获得第一个广告系列
  • 下一批收件人获得第二个活动
  • 等等

这样您只需将列表随机播放一次。而且您不必跟踪哪些用户已经进行了活动。


例子:

  • 用户:1 2 3 4 5 6
  • 广告系列:1 2

随机播放您的用户:

  • 用户:(5 3 2 4 1 6)
  • 用户 (5 3 2) 获得活动 1
  • 用户 (4 1 6) 获得活动 2

【讨论】:

  • 问题是通过将活动 ID 分配给收件人的 N 个对象 - 它非常慢。有没有办法在一行中完成而不是使用 ForEach?
  • 另外,打乱广告系列列表,以确保当广告系列>收件人时不只发送前几个广告系列。
  • 我加了一个例子。
  • 这是一个非常好的建议,但我的问题仍然是为一组 5k 收件人分配一个挑选的活动 ID,我的方法非常慢,有什么快速的方法吗?
  • @B.Simboliq: 你确定它的分配速度很慢而不是PartialRecipients.ToList()
猜你喜欢
  • 2019-12-09
  • 2018-01-16
  • 2016-09-16
  • 1970-01-01
  • 2019-10-23
  • 2018-06-29
  • 2011-12-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多