gpt4 book ai didi

c# - 在 C# 中优化算法和/或结构

转载 作者:太空狗 更新时间:2023-10-29 17:58:32 24 4
gpt4 key购买 nike

我正在开发一个应用程序,您可以在其中订阅时事通讯并选择要订阅的类别。有两组不同的类别:城市和类别。

在发送电子邮件(这是一个预定的尝试)时,我必须在发送电子邮件之前查看订阅者订阅了哪些城市和哪些类别。也就是说,如果我订阅了“伦敦”和“曼彻斯特”作为我选择的城市,并选择了“食品”、“布料”和“电子产品”作为我的类别,我将只会收到与这些相关的时事通讯。

结构如下:

在 Umbraco CMS 中的每个 newsitem 上都有一个以逗号分隔的城市和类别字符串(实际上,它们存储为节点 ID,因为城市和类别也是 Umbraco 中的节点)当我订阅一个或多个城市和一个或多个类别时,我将城市和类别 nodeids 存储在数据库中的自定义表中。我的关系映射如下所示:

enter image description here

整个结构如下所示:

enter image description here

对我来说,这似乎是两组 1 - 1..* 关系(一个订阅者订阅一个或多个城市,一个订阅者订阅一个或多个类别)

要查找向哪个订阅者发送哪些电子邮件,我的代码如下所示:

private bool shouldBeAdded = false;

// Dictionary containing the subscribers e-mail address and a list of news nodes which should be sent
Dictionary<string, List<Node>> result = new Dictionary<string, List<Node>>();

foreach(var subscriber in subscribers)
{
// List of Umbraco CMS nodes to store which nodes the html should come from
List<Node> nodesToSend = new List<Node> nodesToSend();

// Loop through the news
foreach(var newsItem in news)
{
// The news item has a comma-separated string of related cities
foreach (string cityNodeId in newsItem.GetProperty("cities").Value.Split(','))
{
// Check if the subscriber has subscribed to the city
if(subscriber.CityNodeIds.Contains(Convert.ToInt32(cityNodeId)))
{
shouldBeAdded = true;
}
}

// The news item has a comma-separated string of related categories
foreach (string categoryNodeId in newsItem.GetProperty("categories").Value.Split(','))
{
// Check if the subscriber has subscribed to the category
if(subscriber.CategoryNodeIds.Contains(Convert.ToInt32(categoryNodeId)))
{
shouldBeAdded = true;
}
}
}

// Store in list
if (shouldBeAdded)
{
nodesToSend.Add(newsItem);
}

// Add it to the dictionary
if (nodesToSend.Count > 0)
{
result.Add(subscriber.Email, nodesToSend);
}
}

// Ensure that we process the request only if there are any subscribers to send mails to
if (result.Count > 0)
{
foreach (var res in result)
{
// Finally, create/merge the markup for the newsletter and send it as an email.
}
}

虽然这可行,但我有点担心达到一定数量的订阅者时的性能,因为我们进入了三个嵌套的 foreach 循环。另外,请记住我的老老师们的教导:“对于每个 for 循环,都有一个更好的结构”

那么,我想听听您对上述解决方案的看法,对于给定的结构,这里有什么可以改进的地方吗?随着时间的推移,它会导致性能问题吗?

非常感谢任何帮助/提示! :-)

提前致谢。

解决方案

因此,经过几个小时的调试和摸索,我终于想出了一些可行的方法(最初,它看起来像我的原始代码有效,但实际上没有)

遗憾的是,我无法让它与我尝试过的任何 LINQ 查询一起使用,所以我回到了“ol'school' 迭代方式;-)最终算法如下所示:

private bool shouldBeAdded = false;

// Dictionary containing the subscribers e-mail address and a list of news nodes which should be sent
Dictionary<string, List<Node>> result = new Dictionary<string, List<Node>>();

foreach(var subscriber in subscribers)
{
// List of Umbraco CMS nodes to store which nodes the html should come from
List<Node> nodesToSend = new List<Node> nodesToSend();

// Loop through the news
foreach(var newsItem in news)
{
foreach (string cityNodeId in newsItem.GetProperty("cities").Value.Split(','))
{
// Check if the subscriber has subscribed to the city
if (subscriber.CityNodeIds.Contains(Convert.ToInt32(cityNodeId)))
{
// If a city matches, we have a base case
nodesToSend.Add(newsItem);
}
}

foreach (string categoryNodeId in newsItem.GetProperty("categories").Value.Split(','))
{
// Check if the subscriber has subscribed to the category
if (subscriber.CategoryNodeIds.Contains(Convert.ToInt32(categoryNodeId)))
{
shouldBeAdded = true;

// News item matched and will be sent. Stop the loop.
break;
}
else
{
shouldBeAdded = false;
}
}

if (!shouldBeAdded)
{
// The news item did not match both a city and a category and should not be sent
nodesToSend.Remove(newsItem);
}
}

if (nodesToSend.Count > 0)
{
result.Add(subscriber.Email, nodesToSend);
}
}

// Ensure that we process the request only if there are any subscribers to send mails to
if (result.Count > 0)
{
foreach (var res in result)
{
// StringBuilder to build markup for newsletter
StringBuilder sb = new StringBuilder();

// Build markup
foreach (var newsItem in res.Value)
{
// build the markup here
}

// Email logic here
}
}

最佳答案

首先,您可以在shouldBeAdde = true中断 内部foreach。

您也可以使用 LINQ,但我不确定它是否会更快(但您可以使用 .AsParallel 使其轻松实现多线程):

var nodesToSend = from n in news
where n.GetProperties("cities").Value.Split(',')
.Any(c => subscriber.CityNodeIds.Contains(Convert.ToInt32(c)) &&
n.GetProperties("categories").Value.Split(',')
.Any(c => subscriber.CategoryNodeIds.Contains(Convert.ToInt32(c))
select n;

完整的想法将归结为(包括并行):

Dictionary<string, IEnumerable<Node>> result = new Dictionary<string, IEnumerable<Node>>();
foreach(var subscriber in subscribers)
{
var nodesToSend = from n in news.AsParallel()
where n.GetProperties("cities").Value.Split(',')
.Any(c => subscriber.CityNodeIds.Contains(Convert.ToInt32(c)) &&
n.GetProperties("categories").Value.Split(',')
.Any(c => subscriber.CategoryNodeIds.Contains(Convert.ToInt32(c))
select n;

if (nodesToSend.Count > 0)
result.Add(subscriber.Email, nodesToSend);
}

if (result.Count > 0)
{
foreach (var res in result)
{
// Finally, create/merge the markup for the newsletter and send it as an email.
}
}

关于c# - 在 C# 中优化算法和/或结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9615262/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com