4

所以,这是我的问题,我有一个给定的对象,它是一个 IEnumerable,并且我已经保证该集合总是最多有 4 个元素。现在,出于一个不重要的原因,我希望能够以某种优雅的方式“强制”集合包含 4 个元素(如果它有任何更少)。

我已经做了一些研究,最有说服力的候选者是 Zip,但它会在到达最短集合结束后停止压缩。

有没有办法在不制作我自己的扩展方法的情况下做到这一点?为了更好地解释我自己:

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.

提前致谢!

4

3 回答 3

4

快速单线(应该算作“没有扩展方法的可行”):

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

由于Repeat需要显式计数,因此传入会n给出合理的上限。无论如何,这些元素都是按需生成的。使用source.Count()会强制执行source不理想的操作。

稍微过度设计和灵活的版本:

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);
}
于 2012-12-13T23:14:26.063 回答
3

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

这将附加类型的默认值(null在这种情况下):

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

或者,如果您想提供默认值:

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

或者,如果你想拥有那些编号的小狗:

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

Pad如果它的长度已经等于或大于您的焊盘大小,该方法将不会添加额外的条目。

Pad如果您想在不引入整个项目的情况下合并/调整它,这是具体的实现: http ://code.google.com/p/morelinq/source/browse/MoreLinq/Pad.cs

于 2012-12-13T23:11:32.353 回答
0
    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++;
            }
        }
    }
于 2012-12-13T23:17:12.797 回答