我正在使用C#创建一个包含NodaTime.IsoDayOfWeek
天列表的函数。我想将输入分组为连续几天。
例如,以下列表应提供以下输出:
{ Mon, Tue } => { { Mon, Tue } }
{ Mon, Wed } => { { Mon }, { Wed } }
{ Mon, Tue, Fri, Sat } => { { Mon, Tue }, { Fri, Sat } }
{ Mon, Wed, Fri, Sun } => { { Sun, Mon }, { Wed }, { Fri } }
{ Mon, Tue, Wed, Thu, Fri, Sat, Sun } => { { Mon, Tue, Wed, Thu, Fri, Sat, Sun } }
请注意,星期日和星期一是连续的,因此列表是一个闭环。此外,应该对结果列表进行排序,使得第一天直接在输入列表中未包含的日期之后(如果包含完整列表,则为星期一)。
Mauricio Scheffer published a great extension method to group consecutive integers here:
public static IEnumerable<IEnumerable<int>> GroupConsecutive(this IEnumerable<int> list) {
var group = new List<int>();
foreach (var i in list) {
if (group.Count == 0 || i - group[group.Count - 1] <= 1)
group.Add(i);
else {
yield return group;
group = new List<int> {i};
}
}
yield return group;
}
但是我无法弄清楚如何将此修改为分组天数,因为星期日和星期一也是连续的。如何将周日和周一连续几天分组?
答案 0 :(得分:1)
样本输入是有序数组。想象一下,您的输入是1到7之间的数组而不是顺序,您必须使用2个循环来按条件<?php
//blog posts shortcode
function my_recent_post()
{
global $post;
$html = "";
$my_query = new WP_Query( array(
'post_type' => 'post',
'cat' => '4',
'posts_per_page' => 1
));
if( $my_query->have_posts() ) : while( $my_query->have_posts() ) : $my_query->the_post();
$html .= "<span>" . the_post_thumbnail( 'medium', array( 'class' => 'img-responsive') ) . "</span>";
$html .= "<h2>" . the_title() . "</h2>";
$html .= "<p>" . the_excerpt() . "</p>";
endwhile; endif;
return $html;
}
add_shortcode( 'blog', 'my_recent_post' );
?>
查找每个下一个数字。
这是我对你的解决方案的想法:
Abs(current-next) == 1 || Abs(current-next) == 6
答案 1 :(得分:1)
我没有更有效地使用LINQ,但我认为这样做。这只是一个简单的控制台App。
public enum Days
{
Mon = 1,
Tue,
Wed,
Thur,
Fri,
Sat,
Sun
}
public static IEnumerable<IEnumerable<int>> GroupDay(IEnumerable<int> ListOfDays)
{
List<List<int>> Response = new List<List<int>>();
List<int> Queue = new List<int>();
var ListToIterate = ListOfDays.Distinct().OrderBy(d => d).ToList();
foreach (var item in ListToIterate)
{
if (Queue.Count == 0)
{
Queue.Add(item);
}
else
{
if ((item - 1) == Queue[Queue.Count - 1])
{
Queue.Add(item);
}
else if (item != (int)Days.Sun)
{
Response.Add(Queue);
Queue = new List<int>() { item };
}
}
if (item == ListToIterate.LastOrDefault())
Response.Add(Queue);
//Handle Sunday
if (item == (int)Days.Sun)
{
//Check if Saturday exists, if exists then do not put sunday before Monday.
var FindSaturday = Response.Where(r => r.Contains((int)Days.Sat)).FirstOrDefault();
if (FindSaturday == null)
{
var FindMonday = Response.Where(r => r.Contains((int)Days.Mon)).FirstOrDefault();
if (FindMonday != null)
{
FindMonday.Insert(0, item);
}
}
}
}
return Response;
}
以下是我尝试使用某些用例的方法。
//List<int> ListOfDays = new List<int>() { DaysToNumber(Days.Mon), DaysToNumber(Days.Tue) };
//List<int> ListOfDays = new List<int>() { DaysToNumber(Days.Mon), DaysToNumber(Days.Wed) };
//List<int> ListOfDays = new List<int>() { DaysToNumber(Days.Mon), DaysToNumber(Days.Tue), DaysToNumber(Days.Fri), DaysToNumber(Days.Sat) };
//List<int> ListOfDays = new List<int>() { DaysToNumber(Days.Mon), DaysToNumber(Days.Wed), DaysToNumber(Days.Fri), DaysToNumber(Days.Sun) };
//List<int> ListOfDays = new List<int>() { DaysToNumber(Days.Mon), DaysToNumber(Days.Tue), DaysToNumber(Days.Wed), DaysToNumber(Days.Thur), DaysToNumber(Days.Fri), DaysToNumber(Days.Sat), DaysToNumber(Days.Sun) };
List<int> ListOfDays = new List<int>() { DaysToNumber(Days.Mon),DaysToNumber(Days.Fri), DaysToNumber(Days.Sun) };
var ListToIterate = ListOfDays.Distinct().OrderBy(d => d).ToList();
var result = GroupDay(ListToIterate);
答案 2 :(得分:0)
这是我最终选择的解决方案。我在这里使用过Linq,但它可以很容易地重写。我还为此编写了大量的单元测试,如果您想访问它们,请发表评论。
using NodaTime;
using System.Collections.Generic;
using System.Linq;
namespace Domain.Extensions
{
public static class IsoDayOfWeekExtensions
{
public static IReadOnlyList<IReadOnlyList<IsoDayOfWeek>> GroupConsecutive(this IList<IsoDayOfWeek> days)
{
var groups = new List<List<IsoDayOfWeek>>();
var group = new List<IsoDayOfWeek>();
var daysList = days.Distinct().OrderBy(x => (int)x);
foreach (var day in daysList)
{
if (!group.Any() || (int)day - (int)group.Last() == 1)
{
group.Add(day);
}
else
{
groups.Add(group);
group = new List<IsoDayOfWeek>() { day };
}
}
// Last group will not have been added yet. Check if the last group can be combined with the first group (Sunday and Monday are also consecutive!)
if (group.Contains(IsoDayOfWeek.Sunday) && groups.Any() && groups.First().Contains(IsoDayOfWeek.Monday))
{
// Insert before the Monday so that the days are in the correct consecutive order.
groups.First().InsertRange(0, group);
}
else
{
groups.Add(group);
}
return groups.Select(x => x.ToList()).ToList();
}
}
}