简体   繁体   中英

Take more items from list than the list actually has

Hello I want to take 6 items from a list with 5 items at all. And I want to start taking the items at a given position. My result should be saved in another list.

For example:

List_1 = 1, 2, 3, 4, 5  

6 items needed

start at position 2 {= 3}

List_result = 3, 4, 5, 1, 2, 3

List_1 = 7, 13, 6, 9, 17 

2 items needed  

start at position 4 {= 17}

List_result = 17, 7

I already tried to loop through the list with for and foreach, but could not find a real solution. Any help is greatly appreciated!

Something like this will do the trick. I wrote it up quickly, so I'm sure you can make it nicer

private IEnumerable<int> DoSomething(IEnumerable<int> set, int start, int num) {
    var taken = 0;
    var curSet = set.Skip(start);
    while (taken < num) {
        foreach(var current in curSet)
        {
            if (taken == num)
                yield break;
            yield return current;
            taken++;
        }
        curSet = set;
    }
}

Use like this:

DoSomething(new int[] { 1,2,3,4,5}, 2, 6);
Yields:
3,4,5,1,2,3

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");
        var data = new List<int>(5){1,2,3,4,5};
        var result = new List<int>(5);
        for(int i=0;i<5;i++)
        {
            result.Add(data[(i+2)%data.Count]);
        }
        for(int i=0;i<result.Count;i++)
        {
            Console.WriteLine(string.Format("{0}\n",result[i]));
        }
    }
}

simple,

public static IEnumerable<T> TakeLoop<T>(
        this IEnumerable<T> source,
        int count,
        int start = 0)
{
    if (start < 0)
    {
        throw new ArgumentOutOfRangeException("start");
    }

    if (count < 0)
    {
        throw new ArgumentOutOfRangeException("count");
    }

    using (var m = source.GetEnumerator())
    {
        for (var i = 0; i < count + start; i++)
        {
            if (!m.MoveNext())
            {
                if (i < start)
                {
                    throw new ArgumentOutOfRangeException("start");
                }

                m.Reset();
                m.MoveNext();
            }

            if (i >= start)
            {
                yield return m.Current;
            }
        }
    }
}

to be used, like this,

var result1 = (new[] { 1, 2, 3, 4, 5 }).TakeLoop(6, 3);

or this,

var result2 = (new[] { 7, 13, 6, 9, 17 }).TakeLoop(2, 4);

You could use this extension:

public static IEnumerable<T> TakeSpinning<T>(this IEnumerable<T> source, int take, int position = 0)
{
    // skip check for invalid input like negative take or position
    int skip = position;
    int taken = 0;
    while (taken < take)
    {
        foreach (T element in source)
        {
            if (skip > 0)
            {
                skip--;
                continue;
            }
            yield return element;
            if (++taken == take) break;
        }
    }
}

Your samples:

var List_1 = new List<int> { 1, 2, 3, 4, 5 };
var List_Result = List_1.TakeSpinning(6, 2).ToList();  // 3,4,5,1,2,3

var List_2 = new List<int> { 7, 13, 6, 9, 17 }; 
var List_Result2 = List_2.TakeSpinning(2, 4).ToList(); // 17,7

its a simple iteration , you can use a simple loop to do this:

List list;// add values
int itemNeeded; //set item need

int startPostion; //set the start postion
for(int i=0;i<itemNeeded;i++){
  add to newList the item at (startPosition++ % length of list)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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