根据属性值将项目拆分为N个项目

时间:2019-09-06 11:20:48

标签: c# linq

根据属性值将N个项目拆分为一个项目。

问题:

我们有一个List<Movie>Movie拥有类型为Genre="1;2;3"的流派 我们将一部电影拆分为N部电影,流派数为n。

不是每个电影都有多种流派的电影列表。 我们想要一个电影列表,其中每部电影只有一种类型。

Movie{Genre="1;2;3",Title="3 Time" }
=> 
Movie{Genre="1",Title="3 Time" },
Movie{Genre="2",Title="3 Time" },
Movie{Genre="3",Title="3 Time" }

MRE:


    var separator = ";".ToCharArray();
    var inputs = new[]{
        new Movie{Genre="1;2;3",Title="3 Time" },
        new Movie{Genre="1;2",Title="Twice" },
        new Movie{Genre="1",Title="Once" }
    };

    var expectedResult = new[]{
        new Movie{Genre="1",Title="3 Time" },
        new Movie{Genre="2",Title="3 Time" },
        new Movie{Genre="3",Title="3 Time" },

        new Movie{Genre="1",Title="Twice" },
        new Movie{Genre="2",Title="Twice" },

        new Movie{Genre="1",Title="Once" }
    };

    var results = new List<Movie> { };
    foreach (var item in inputs)
    {
        foreach (var subGenre in item.Genre.Split(separator, StringSplitOptions.RemoveEmptyEntries))
        {
            results.Add(new Movie { Genre = subGenre, Title = item.Title });
        }
    }

    var valid = results.SequenceEqual(expectedResult);


    public partial class Movie 
    {
        public string Genre { get; set; }
        public string Title { get; set; }
    }

    //For Unit Testing and Sequence Equal. Not need for reproduction
    public partial class Movie : IEquatable<Movie>
    {
        public bool Equals(Movie movie)
        {
            if (movie is null)
            {
                return false;
            }
            return this.Genre == movie.Genre && this.Title == movie.Title;

        }
        public override bool Equals(object obj) => Equals(obj as Movie);
        public override int GetHashCode()
        {
            return (Title, Genre).GetHashCode();
        }

        public static bool operator ==(Movie i1, Movie i2)
        {
            return i1.Equals(i2);
        }
        public static bool operator !=(Movie i1, Movie i2)
        {
            return !(i1.Equals(i2));
        }

    }

是否有LinQ方法可以进行双重foreach治疗?

如果列表中的字符串感觉不自然,这是Genre是数组的版本:

inputs.Select(x =>
    new
    {
        splittedProperty = x.Genre.Split(separator, StringSplitOptions.RemoveEmptyEntries).ToArray(),
        x.Title
    });

1 个答案:

答案 0 :(得分:1)

可以使用SelectMany LINQ方法轻松完成此操作:

var movies = inputs.SelectMany(
    m => m.Genre.Split(new[] {";"}, StringSplitOptions.RemoveEmptyEntries).Select(g => new Movie(g, m.Title))
);

我在Movie类中添加了另一个构造函数,但是您也可以使用类初始化程序:

public partial class Movie
{
    public Movie()
    {

    }

    public Movie(string genre, string title)
    {
        Genre = genre;
        Title = title;
    }

    public string Genre { get; set; }
    public string Title { get; set; }
}
相关问题