将2个集合汇总到父母/孩子

时间:2018-06-21 16:58:33

标签: c# parent-child

我不确定我找到的解决这个问题的方法是否正确。

示例场景:

class FolderItem
{
    public int Id { get; set; }
    public string Name { get; set; }
    public FileItem[] Files { get; set; }
}

class FileItem
{
    public int Id { get; set; }
    public int FolderId { get; set; }
    public string Name { get; set; }
    public byte[] Content { get; set; }
}

从2个收藏开始:

FolderItem[] folders = 
    new FolderItem[]
    {
        new FolderItem
        {
            Id = 1,
            Name = "Folder1"
        },
        new FolderItem
        {
            Id = 2,
            Name = "Folder2"
        }
    };

FileItem[] files = 
    new FileItem[]
    {
        new FileItem
        {
            Id = 100,
            FolderId = 1,
            Name = "file1.txt",
            Content = new byte[] { 1, 2, 3 }
        },
        new FileItem
        {
            Id = 200,
            FolderId = 1,
            Name = "file2.txt",
            Content = new byte[] { 1, 2, 3 }
        },
        new FileItem
        {
            Id = 300,
            FolderId = 2,
            Name = "file3.txt",
            Content = new byte[] { 1, 2, 3 }
        },
        new FileItem
        {
            Id = 400,
            FolderId = 2,
            Name = "file4.txt",
            Content = new byte[] { 1, 2, 3 }
        }
    };

为了将“ FileItem”放入“文件夹”的属性“文件”中,我这样做:

 files
    .Join
    (
        folders,
        x => x.FolderId,
        x => x.Id,
        (x,y) => new { File = x, Folder = y }
    )
    .GroupBy(x => x.Folder.Id)
    .Select
    (x => 
        { 
            var folder = x.First().Folder;
            folder.Files = x.Select(z => z.File).ToArray();
            return folder;
        }
    )

我可以在.First() lambda中使用GroupBy,因为我正在按其ID分组

我得到:

enter image description here

是否有一些扩展方法可以比此方法更快或更好?有什么最佳做法吗?

2 个答案:

答案 0 :(得分:1)

只需使用Where创建一个新列表即可获取每个文件夹的文件。

var foldersWithFiles = folders
    .Select
    (
        folder =>
        new FolderItem
        {
            Id = folder.Id,
            Name = folder.Name,
            Files = files.Where
            (
                file => file.FolderId = folder.Id
            ).ToArray()
        )
    );

您以后总是可以替换旧列表,如下所示:

folders = foldersWithFiles.ToArray();

答案 1 :(得分:1)

您可以简单地循环播放文件夹并将项目添加到它们各自的文件夹中。 首先,您需要在各处将FileItem[]更改为List<FileItem>,将FolderItem[]更改为List<FolderItem>

您需要像这样的List的删除并获取扩展方法。优化此功能可删除元素,同时仍返回它们,从而减少数量 后续迭代。

public static List<T> RemoveAndGet<T>(this List<T> list, Func<T, bool> predicate)
{
    var itemsRemoved = new List<T>();

    // iterate backward for performance
    for (int i = list.Count - 1; i >= 0; i--)
    {
        // keep item pointer
        var item = list[i];

        // if the item match the remove predicate
        if (predicate(item))
        {
            // add the item to the returned list
            itemsRemoved.Add(item);

            // remove the item from the source list
            list.RemoveAt(i);
        }
    }

    return itemsRemoved;
}

然后,您唯一的查询就是用此查询填充当前的文件夹。

 folders.ForEach(folder => 
     folder.Files.AddRange(files.RemoveAndGet(file => file.FolderId == folder.Id)));