以递归方式从列表的开头和结尾同时删除元素

时间:2015-11-14 05:48:14

标签: c#

如果第一个和最后一个元素满足条件,我想同时从列表的开头和结尾删除元素。

我的课程名称为Day,如下所示

public class Day
{
    public String Name{get; set;}
    public bool IsActive{get; set;}
}

我有一个包含所有日期的列表IList<Day> Days。现在我想从开始和结束中删除元素,如果列表中的开始或结束元素,即Day满足此条件:Day.IsActive == true

我想继续从开始和结束中删除列表中的元素(以使其更有效),同时直到列表在开始和结束时没有元素的点Day.IsActive == true

所以案件可能是

  1. active-inactive-inactive-active-active
  2. 主动 - 主动
  3. 活性非活性
  4. 非活性非活性
  5. 这就是我想出来的,它解决了问题,但有更好的方法可以做到

    public IList<Day> RemoveDays(IList<Day> days) 
            {
                while (days.Count > 0 && (days.First().IsActive || days.Last().IsActive))
                {
                    if(days.First().IsActive)
                        days.RemoveAt(0);
                    if (days.Count > 0 && days.Last().IsActive)
                        days.RemoveAt(days.Count - 1);
                    return RemoveDays(days);
                }
    
                return days;
            }
    

5 个答案:

答案 0 :(得分:0)

尝试

            while (list.Count > 2)
            {
                if (list[0].IsActive || list[list.Count - 1].IsActive)
                {
                    list.RemoveAt(list.Count - 1);
                    list.RemoveAt(0);
                }
                else
                    break;
            }

更新1:

  

现在我想要从开始以及结束时删除元素   列表中的开始或结束元素,即完整填写此条件的日期:   Day.IsActive == true。

根据你的陈述,我认为你要求在开始或结束时删除元素IsActive = true

如果没有,请使用以下

            while (list.Count > 2)
            {
                if (list[0].IsActive && list[list.Count - 1].IsActive)
                {
                    list.RemoveAt(list.Count - 1);
                    list.RemoveAt(0);
                }
                else
                    break;
            }

答案 1 :(得分:0)

这是一个解决方案。我假设任务的递归部分是必需的,所以它是递归完成而不是迭代方法:

class Program
{
    public static IList<Day> ClearList(IList<Day> days)
    {
        return days.First().IsActive && days.Last().IsActive ?
            ClearList((days.Skip(1).Take(days.Count - 2)).ToList()) :
            days;
    }

    static void Main(string[] args)
    {
        List<Day> days = new List<Day>
        {
            new Day {IsActive = true, Name="M" },
            new Day {IsActive = true, Name="T" },
            new Day {IsActive = false, Name="W" },
            new Day {IsActive = false, Name="Th" },
            new Day {IsActive = true, Name="F" },
            new Day {IsActive = true, Name="St" },
            new Day {IsActive = true, Name="Su" },
        };

        var cleared = ClearList(days);
    }
}

首先在ClearList方法内部检查两端是否都处于活动状态。如果是这样,请先跳过,除了最后一个之外,将其他所有其他内容再次传递给ClearList方法。否则,返回集合。

答案 2 :(得分:0)

Linq风格的递归方法怎么样?

public static List<Day> Check(List<Day> days) {
    if (days.Count < 2)
        return days;
    else if (days.First().IsActive || days.Last().IsActive) {
        var daysInBetween = days.Take(days.Count - 1).Skip(1);
        return Check(daysInBetween);
    }
    else
        return days;
}

答案 3 :(得分:0)

以下实现了一个trim方法,用于从开始和结束中删除活动项。递归地执行此操作没有特别的好处,配对删除也没有太大的好处。

因为从前面删除是O(n)操作(即它最终复制列表中的每个元素),可能最快的方法是从末尾删除活动元素,然后从前面删除:

while (theList.Count > 0 && theList[theList.Count-1].IsActive)
{
    theList.RemoveAt(theList.Count-1);
}

现在确定从前面移除多少。

int ix = 0;
while (theList[ix].IsActive)
{
    ++ix;
}

// copy remaining items to the front
int dest = 0;
if (ix > 0)
{
    for (int i = ix; i < theList.Count-1; ++i)
    {
        theList[dest] = theList[i];
        ++dest;
    }
    // and remove the last ix items from the end
    while (ix > 0)
    {
        theList.RemoveAt(theList.Count-1);
        --ix;
    }
}

这就是就地操作。如果您对创建新列表感到满意,那就更容易了:

int lastItem = theList.Count-1;
while (theList.Count > 0 && theList[lastItem].IsActive)
{
    lastItem = lastItem - 1;
}

int firstItem = 0;
while (theList[firstItem].IsActive)
{
    ++firstItem;
}

// copy items to create a new list
theList = theList.Skip(firstItem)
    .Take(lastItem - firstItem)
    .ToList();

答案 4 :(得分:0)

这就是我想出来的,希望它会帮助别人。

public IList<Day> RemoveDays(IList<Day> days)
{
    while (true)
    {
        if (days.Count <= 0 || !(days.First().IsActive || days.Last().IsActive)) return days;
        if (days.First().IsActive)
            days.RemoveAt(0);
        if (days.Count > 0 && days.Last().IsActive)
            days.RemoveAt(days.Count - 1);
    }
}