分组连续元素并选择第一个和最后一个元素

group continuous elements and select first and last element [duplicate]
2021-05-11
  •  译文(汉语)
  •  原文(英语)

以下是我的清单

List<DateTime> ls_date =new List<DateTime>()
ls_date.Add("2013-12-02")
ls_date.Add("2013-12-03")
ls_date.Add("2013-12-04")
ls_date.Add("2013-12-05")
ls_date.Add("2013-12-08")
ls_date.Add("2013-12-12")
ls_date.Add("2013-12-13")
ls_date.Add("2013-12-14")

我想对连续日期进行分组,然后选择该组的开始和结束日期

输出:

"2013-12-02"-"2013-12-05"
"2013-12-08"-"2013-12-08"
"2013-12-12"-"2013-12-14"

我的尝试:

public class sampleWithIntervals
{
 public DateTime startDate;
 public DateTime endDate;
}
    var data = ls_date
            .Select((s, i) => new { sample = s, index = i })                
            .GroupBy(si => new { date = si.sample.Date.AddDays(-si.index) })                
            .Select(g => new sampleWithIntervals()
            {
                startDate = g.Min(s => s.sample.Date),
                endDate = g.Max(s => s.sample.Date)

            });

我怎样才能做到这一点?

速聊1:
您可以从我的(codereview.stackexchange.com/questions/6512/…)函数开始,或者从答案之一开始.
速聊2:
List<DateTime> ls_date =new List<DateTime>(); ls_date.Add("2013-12-02");不会编译:字符串不是,DateTime除非它们被解析为.
速聊3:
对不起,我正在转换并添加到列表中
解决过程1

这是一个辅助函数,该函数根据采用当前项目和先前项目的功能对项目进行分组,以确定该项目应该在现有组中还是在新组中:

public static IEnumerable<IEnumerable<T>> GroupWhile<T>(
    this IEnumerable<T> source, Func<T, T, bool> predicate)
{
    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
            yield break;

        List<T> list = new List<T>() { iterator.Current };

        T previous = iterator.Current;

        while (iterator.MoveNext())
        {
            if (predicate(previous, iterator.Current))
            {
                list.Add(iterator.Current);
            }
            else
            {
                yield return list;
                list = new List<T>() { iterator.Current };
            }

            previous = iterator.Current;
        }
        yield return list;
    }
}

现在您可以编写:

var intervals = dates.GroupWhile((prev, next) => 
        prev.Date.AddDays(1) == next.Date)
    .Select(g => new sampleWithIntervals()
    {
        startDate = g.Min(s => s.Date),
        endDate = g.Max(s => s.Date)
    });
速聊1:
我没有得到任何结果清单
速聊2:
在我编写的测试中效果很好.也许您的输入数据集为空.
速聊3:
我已经在一个静态类中定义了这个静态方法.那是对的吗?
速聊4:
如果您编辑并发布您的完整示例代码,那将是很好的
速聊5:
是的,它应该在静态类中.如果可以编译,那么显然这不是问题.如果获取的结果集为空,则唯一的选择是您的数据源为空.您只需要在其中创建一个数组DateTime.Today即可看到它从中创建一个组.

Below is my List

List<DateTime> ls_date =new List<DateTime>()
ls_date.Add("2013-12-02")
ls_date.Add("2013-12-03")
ls_date.Add("2013-12-04")
ls_date.Add("2013-12-05")
ls_date.Add("2013-12-08")
ls_date.Add("2013-12-12")
ls_date.Add("2013-12-13")
ls_date.Add("2013-12-14")

I want to group continuous date and select start and end date of that group

Output:

"2013-12-02"-"2013-12-05"
"2013-12-08"-"2013-12-08"
"2013-12-12"-"2013-12-14"

My try:

public class sampleWithIntervals
{
 public DateTime startDate;
 public DateTime endDate;
}
    var data = ls_date
            .Select((s, i) => new { sample = s, index = i })                
            .GroupBy(si => new { date = si.sample.Date.AddDays(-si.index) })                
            .Select(g => new sampleWithIntervals()
            {
                startDate = g.Min(s => s.sample.Date),
                endDate = g.Max(s => s.sample.Date)

            });

How can i achieve this?

Talk1:
You could start with my (codereview.stackexchange.com/questions/6512/…) function or one of the answers.
Talk2:
List<DateTime> ls_date =new List<DateTime>(); ls_date.Add("2013-12-02"); will not compile: strings aren't DateTimes unless they're parsed to be.
Talk3:
sorry.i'm converting and adding into list
Solutions1

Here is a helper function that groups items based on a function that takes the current and previous items determines if that item should be in the existing group, or a new group:

public static IEnumerable<IEnumerable<T>> GroupWhile<T>(
    this IEnumerable<T> source, Func<T, T, bool> predicate)
{
    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
            yield break;

        List<T> list = new List<T>() { iterator.Current };

        T previous = iterator.Current;

        while (iterator.MoveNext())
        {
            if (predicate(previous, iterator.Current))
            {
                list.Add(iterator.Current);
            }
            else
            {
                yield return list;
                list = new List<T>() { iterator.Current };
            }

            previous = iterator.Current;
        }
        yield return list;
    }
}

Now you can write:

var intervals = dates.GroupWhile((prev, next) => 
        prev.Date.AddDays(1) == next.Date)
    .Select(g => new sampleWithIntervals()
    {
        startDate = g.Min(s => s.Date),
        endDate = g.Max(s => s.Date)
    });
Talk1:
i'm not getting any list as result
Talk2:
Works just fine in a test I wrote. Perhaps your input data set is empty.
Talk3:
i've defined this static method inside a static class. Is that correct?
Talk4:
It would be good if you edit and post full sample code of yours
Talk5:
Yes, it should be in a static class. If it compiles, then clearly that's not an issue. If you're getting an empty result set then the only option is that you have an empty data source. You only need to create an array with DateTime.Today in it to see it create a group from it.
转载于:https://stackoverflow.com/questions/20200073/group-continuous-elements-and-select-first-and-last-element

本人是.net程序员,因为英语不行,使用工具翻译,希望对有需要的人有所帮助
如果本文质量不好,还请谅解,毕竟这些操作还是比较费时的,英语较好的可以看原文

留言回复
我们只提供高质量资源,素材,源码,坚持 下了就能用 原则,让客户花了钱觉得值
上班时间 : 周一至周五9:00-17:30 期待您的加入