简体   繁体   English

如何从 C# 中的列表中删除每个第 n 项?

[英]How can I remove every nth item from a list in C#?

I would like to recreate the MASH game as a console application.我想将MASH 游戏重新创建为控制台应用程序。

I currently have the code in place to receive user input and put the data into separate lists.我目前有代码来接收用户输入并将数据放入单独的列表中。

In my version of the game, the program takes your name and counts how many characters are in it ( numberOfLetters ).在我的游戏版本中,程序会使用你的名字并计算其中有多少个字符( numberOfLetters )。 This is an alternative to drawing a spiral like in the link above.这是在上面的链接中绘制螺旋的替代方法。 It would then use this value to remove every nth value until there is only one of each item in each list.然后它会使用这个值来删除每个第 n 个值,直到每个列表中的每个项目都只有一个。

I am struggling to write the logic for this last section.我正在努力为最后一部分编写逻辑。 I think it would make sense to create a cumulative list and then remove the nth terms, but I am not sure how to tell the program how to leave one item per list.我认为创建一个累积列表然后删除第 n 个术语是有意义的,但我不确定如何告诉程序如何在每个列表中保留一项。

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Welcome to the MASH game!");

        Console.WriteLine("Enter three colleges or universities...");
        List<string> CollegeList = new List<string>();
        for (int i = 0; i < 3; i++)
        {
            CollegeList.Add(Console.ReadLine());
        }

        Console.WriteLine("Enter three babes or dudes that you might marry...");
        List<string> BabeList = new List<string>();
        for (int i = 0; i < 3; i++)
        {
            BabeList.Add(Console.ReadLine());
        }

        Console.WriteLine("Enter three (3) cities which you might live in...");
        List<string> CityList = new List<string>();
        for (int i = 0; i < 3; i++)
        {
            CityList.Add(Console.ReadLine());
        }

        Console.WriteLine("Enter three numbers...");
        List<string> NumberList = new List<string>();
        for (int i = 0; i < 3; i++)
        {
            NumberList.Add(Console.ReadLine());
        }

        Console.WriteLine("Enter three majors...");
        List<string> MajorList = new List<string>();
        for (int i = 0; i < 3; i++)
        {
            MajorList.Add(Console.ReadLine());
        }

        Console.WriteLine("Enter three occupations...");
        List<string> JobList = new List<string>();
        for (int i = 0; i < 3; i++)
        {
            JobList.Add(Console.ReadLine());
        }

        List<string> ShelterList = new List<string>();
        ShelterList.Add("Mansion");
        ShelterList.Add("Apartment");
        ShelterList.Add("Shack");
        ShelterList.Add("House");

        Console.WriteLine("Alright smartass, enter your name");
        string Name = Console.ReadLine();
        int numberOfLetters = Name.ToCharArray().Count();
        Console.WriteLine("........." + numberOfLetters + ".........");

    }
}}

Well, let's state the problem an then solve it.好吧,让我们陈述问题然后解决它。 Having a list, say有一个清单,说

{0, 1, 2, 3, 4, 5, 6, 7, 8}

we want to remove every item startAt from some index, eg我们想从某个索引中删除every项目startAt ,例如

{0, 1, 2, 3, 4, 5, 6, 7, 8} => {0, 1, 2, 3, 5, 7}
          ^  *     *     *      
          |  remove every 2nd item
          |  
          start at 4th item     
   

Code:代码:

// return true if at least one item has been removed
public static bool Remover<T>(List<T> list, int every, int startAt = 0) {
  if (list == null)
    throw new ArgumentNullException(nameof(list));
  if (every <= 0)
    throw new ArgumentOutOfRangeException(nameof(every));

  if (startAt >= list.Count)
    return false;

  int shift = 0;

  for (int i = Math.Max(0, startAt); i < list.Count; ++i) 
    if ((i - startAt) % every == 0)
      shift += 1;
    else
      list[i - shift] = list[i];
  
  list.RemoveRange(list.Count - shift, shift);

  return shift > 0;
}

I am struggling to write the logic for this last section.我正在努力为最后一部分编写逻辑。 I think it would make sense to create a cumulative list and then remove the nth terms, but I am not sure how to tell the program how to leave one item per list.我认为创建一个累积列表然后删除第 n 个术语是有意义的,但我不确定如何告诉程序如何在每个列表中保留一项。

This highly depends on your integer numberOfLetters .这在很大程度上取决于您的整数numberOfLetters Factors such as if this is greater than the size of the list before and after iteration.诸如这是否大于迭代前后列表的大小等因素。

Console.WriteLine("Alright smartass, enter your name");
string Name = Console.ReadLine();
int numberOfLetters = Name.Length;
int len = list.Count;
for(int i=0; i<len; i++) {
   if(numberOfLetters < len && i % numberOfLetters == 0 && len > 1) {
   list.RemoveAt(i);
  }
}

The above logic cannot gurantee that the list will be reduced to 1 item.上述逻辑不能保证列表会减少到 1 项。 If you need this to be down to one last item then you will need to use the random() like this especially if the list size is lesser than the numberOfLetters integer.如果您需要将其减少到最后一项,那么您将需要像这样使用random() ,特别是如果列表大小小于numberOfLetters整数。

Console.WriteLine("Alright smartass, enter your name");
string Name = Console.ReadLine();
int numberOfLetters = Name.Length;
int len = list.Count;
var rdm = new Random();
for(int i=0; i<len; i++) {
   // ignoring the nth item
   if(len > 1) {
   list.RemoveAt(rdm.Next(0, len));
  }
}

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

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