简体   繁体   English

如何使用扩展方法使集合成为“n”元素?

[英]How to make a collection be “n” elements long using extension methods?

So, here is my issue, I have a given object which is an IEnumerable and I have been guaranteed that said collection will always have at most 4 elements. 所以,这是我的问题,我有一个给定的对象,它是一个IEnumerable,我保证所说的集合总是最多有4个元素。 Now, for a reason that is not important, I'd like to be able to, in some elegant way, "force" the collection to contain 4 elements if it has any less. 现在,由于一个不重要的原因,我希望能够以一种优雅的方式“强制”该集合包含4个元素(如果它没有更少)。

I've already done some research and the most convincig candidate is Zip, but it stops zipping after it reaches the shortest collection's end. 我已经完成了一些研究,而且最令人信服的候选人是Zip,但它在收到最短的收集结束后就会停止拉链。

Is there any way of doing this without making my own extension method? 有没有办法在没有自己的扩展方法的情况下这样做? To better explain myself: 为了更好地解释自己:

var list1 = new List<Dog> {
    new Dog { Name = "Puppy" }
}
var list2 = new List<Dog> {
    new Dog { Name = "Puppy1" },
    new Dog { Name = "Puppy2" },
    new Dog { Name = "Puppy3" },
    new Dog { Name = "Puppy4" },
}

var other1 = list1.ExtendToNElements(4).ToList();
//Now other1's first element is an instance of Dog with Name = "Puppy"
//And the following 3 elements are null, or have a Dog with no name
//I don't really care about that

var other2 = list2.ExtendToNElements(4).ToList();
//other2 is the same as list2, nothing got added.

Thanks in advance! 提前致谢!

Quick one-liner (which should count as "doable without an extension method"): 快速单行(应该算作“没有扩展方法可行”):

public static IEnumerable<TItem> Extend<TItem>(
            this IEnumerable<TItem> source, 
            int n)
{
    return source.Concat(Enumerable.Repeat(default(TItem), n))
                 .Take(n);
}

Since Repeat takes an explicit count, passing in n gives a reasonable upper bound. 由于Repeat采用显式计数,因此传入n给出了合理的上限。 The elements are generated on-demand anyway. 无论如何,元素都是按需生成的。 Using source.Count() would force execution of source which isn't ideal. 使用source.Count()会强制执行不理想的source

Slightly more overengineered and flexible version: 稍微过度设计和灵活的版本:

public static IEnumerable<TItem> Extend<TItem>(
            this IEnumerable<TItem> source, 
            int n, 
            Func<TItem> with) 
{
    return source.Concat(
        from i in Enumerable.Range(0, n) select with()
    ).Take(n);
}

public static IEnumerable<TItem> Extend<TItem>(
            this IEnumerable<TItem> source, 
            int n, 
            TItem with = default(TItem)) 
{
    return source.Extend(n, with: () => with);
}

You can use MoreLinq's Pad method: http://code.google.com/p/morelinq/ (NuGet: http://www.nuget.org/packages/morelinq ) 您可以使用MoreLinq的Pad方法: http//code.google.com/p/morelinq/ (NuGet: http ://www.nuget.org/packages/morelinq)

This will append the default value for the type ( null in this case): 这将附加类型的默认值(在本例中为null ):

var other1 = list1.Pad(4).ToList();

Or if you want to supply a default value: 或者,如果要提供默认值:

var other1 = list1.Pad(4, "Puppy_null").ToList();

Or if you want to have those numbered puppies: 或者如果你想要那些编号的小狗:

var other1 = list.Pad(4, (count) => "Puppy" + count).ToList();

The Pad method will not add additional entries if its length is already equal to or greater than your pad size. 如果Pad方法的长度已经等于或大于您的焊盘尺寸,则Pad方法不会添加其他条目。

Here's the Pad implementation specifically if you want to incorporate/adapt it without bringing in the entire project: http://code.google.com/p/morelinq/source/browse/MoreLinq/Pad.cs 如果你想在不引入整个项目的情况下整合/改编它,那么这就是Pad实现: http//code.google.com/p/morelinq/source/browse/MoreLinq/Pad.cs

    class Program
    {
        static void Main(string[] args)
        {
            List<string> list = new List<string>();
            list.Capacity = 4;
            var items = list.TakeOrDefault(4);


        }
    }

    public static class EnumerableExtensions
    {
        public static IEnumerable<T> TakeOrDefault<T>(this IEnumerable<T> enumerable, int length)
        {
            int count = 0;
            foreach (T element in enumerable)
            {
                if (count == length)
                    yield break;

                yield return element;
                count++;
            }
            while (count != length)
            {
                yield return default(T);
                count++;
            }
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM