对于这个简单的 Linq 使用,我的代码效率非常低

发布于 2024-09-08 14:14:14 字数 1170 浏览 5 评论 0原文

我有以下方法,该方法应该解析 XML 响应中的信息并返回用户集合。

我选择创建一个 Friend 类并向调用方法返回一个 List

这是我到目前为止所做的,但我注意到 ids.ToList().Count 方法将每个 id 元素解析为列表,然后在 for 条件中再次执行此操作。简直是超级无效。

public List<Friend> FindFriends()
{
    List<Friend> friendList = new List<Friend>();

    var friends = doc.Element("ipb").Element("profile").Element("friends").Elements("user");
    var ids = from fr in friends
              select fr.Element("id").Value;

    var names = from fr in friends
                select fr.Element("name").Value;

    var urls = from fr in friends
                select fr.Element("url").Value;

    var photos = from fr in friends
                select fr.Element("photo").Value;

    if (ids.ToList().Count > 0)
    {
        for (int i = 0; i < ids.ToList().Count; i++)
        {
            Friend buddy = new Friend();
            buddy.ID = ids.ToList()[i];
            buddy.Name = names.ToList()[i];
            buddy.URL = urls.ToList()[i];
            buddy.Photo = photos.ToList()[i];

            friendList.Add(buddy);
        }
    }            

    return friendList;
}

I have the following method that is supposed to parse information from an XML response and return a collection of users.

I've opted into creating a Friend class and returning a List<Friend> to the calling method.

Here's what I have so far, but I noticed that the ids.ToList().Count method parses every single id element to a List, then does it again in the for conditional. It's just super ineffective.

public List<Friend> FindFriends()
{
    List<Friend> friendList = new List<Friend>();

    var friends = doc.Element("ipb").Element("profile").Element("friends").Elements("user");
    var ids = from fr in friends
              select fr.Element("id").Value;

    var names = from fr in friends
                select fr.Element("name").Value;

    var urls = from fr in friends
                select fr.Element("url").Value;

    var photos = from fr in friends
                select fr.Element("photo").Value;

    if (ids.ToList().Count > 0)
    {
        for (int i = 0; i < ids.ToList().Count; i++)
        {
            Friend buddy = new Friend();
            buddy.ID = ids.ToList()[i];
            buddy.Name = names.ToList()[i];
            buddy.URL = urls.ToList()[i];
            buddy.Photo = photos.ToList()[i];

            friendList.Add(buddy);
        }
    }            

    return friendList;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

花开柳相依 2024-09-15 14:14:14

第一个问题 - 您是否必须返回 List ?您可以返回 IEnumerable 吗?如果是这样,性能会变得更好:

IEnumerable<Friend> FindFriends()
{
    return doc.Descendants("user").Select(user => new Friend {
        ID = user.Element("id").Value,
        Name = user.Element("name").Value,
        Url = user.Element("url").Value,
        Photo = user.Element("photo").Value
    });
}

这会创建一个投影,或者一个仅包含如何<的所有逻辑的新对象,而不是实际创建新的存储桶并将值填充到其中。 /em> 创建新的 Friend 对象而不实际创建它们。当调用者最终开始对 IEnumerable 进行 foreach 时,它们就会被创建。这称为“延迟执行”。

这还做出了一个假设 - XML 片段中的所有 节点都是友元。如果情况并非如此,则 XML 选择的第一部分可能需要稍微复杂一些。

正如 @anon 指出的那样,即使您确实需要返回 List ,但由于某种原因(从您提供的信息来看并不明显),您也可以只调用 .ToList() 在 return 语句的末尾。这只会将我上面描述的投影直接执行到一个新存储桶中,因此您只创建一个。

First question - do you have to return a List<Friend>? Can you return an IEnumerable<Friend> instead? If so, performance gets a lot better:

IEnumerable<Friend> FindFriends()
{
    return doc.Descendants("user").Select(user => new Friend {
        ID = user.Element("id").Value,
        Name = user.Element("name").Value,
        Url = user.Element("url").Value,
        Photo = user.Element("photo").Value
    });
}

Rather than actually creating new buckets and stuffing values into them, this creates a projection, or a new object that simply contains all of the logic for how to create the new Friend objects without actually creating them. They get created when the caller eventually starts to foreach over the IEnumerable. This is called "deferred execution".

This also makes one assumption - All the <user> nodes in your XML fragment are friends. If that isn't true, the first part of the XML selection might need to be a little more complex.

And as @anon points out, even if you do need to return a List<Friend> for some reason not obvious from the information you've provided, you can just call .ToList() at the end of the return statement. This will just execute the projection I described above straight into a new bucket, so you only ever create one.

故人如初 2024-09-15 14:14:14

为什么需要单独的 ids/names/urls/photos 变量?将其全部结合起来。如果不需要列表,可以消除 ToList() 调用。

List<Friend> friendList = (from f in doc.Element("ipb").Element("profile").Element("friends").Elements("user")
                          select new Friend() { 
                                                 ID = f.Element("id").Value, 
                                                 Name = f.Element("name").Value,
                                                 URL = f.Element("url").Value,
                                                 Photo = f.Element("photo").Value
                                 }).ToList();

return friendList;

Why do you need the separate ids/names/urls/photos variables? Combine it all. You can eliminate the ToList() call if you don't need a List.

List<Friend> friendList = (from f in doc.Element("ipb").Element("profile").Element("friends").Elements("user")
                          select new Friend() { 
                                                 ID = f.Element("id").Value, 
                                                 Name = f.Element("name").Value,
                                                 URL = f.Element("url").Value,
                                                 Photo = f.Element("photo").Value
                                 }).ToList();

return friendList;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文