用日期和星座符号填充二维数组的更好方法

时间:2014-04-20 13:13:46

标签: c# arrays date time

我正在解决以下问题:

我想填充一个二维[365,2]数组。第一个值应该保留日期:从1月1日开始到12月31日结束。第二个值应该为每个日期保留相应的星座:

e.g。 array[0, 0]拥有101,array[0, 1]拥有白羊座等等。

我写了一个函数:

public static void fill_array(string[,] year_zodiac, int days, string zodiac, string startdate, int starting_day) 
{
    //function to fill array with date and zodiac
    int startdate_int = 0;
    for (int i = starting_day; i <= days; i++)
    {
        year_zodiac[i, 0] = startdate;
        year_zodiac[i, 1] = zodiac;

        startdate_int = Int32.Parse(startdate);
        startdate_int++;
        startdate = startdate_int.ToString();
    }

并将其称为:

fill_array(main_array, 18, "Aries", "101", 0);

每个十二生肖都必须这样做。我只是简单地拨打fill_array两次就避开了月份休息问题(即我在12月份称之为白羊座一次,而在1月份称之为白羊座一次)。

此解决方案有效,但对我来说似乎非常粗糙。

有人能给我一些更优雅的解决方案吗?

2 个答案:

答案 0 :(得分:10)

这是一个完成你想要的课程,经过测试。我没有在第一个例子中填写所有标志,但是当我重新考虑它时,我做到了。我建议你测试一下,因为我只测试了几个案例,可能错过了一些边缘案例。

正如@ClickRick向我指出的那样,我确实从他的数组/枚举设计开始,但发现在使用Linq并移动到List时缺乏。我还必须修复他的数据数组,以便编译。我应该给予应有的信用。

public class Signs
{
   static List<string> SignList = new List<string>() {  "Aquarius", "Pisces", "Aries", "Taurus", "Not Found"};

   static DateTime[] startDates =  {
        new DateTime(DateTime.Now.Year,1,21),
        new DateTime(DateTime.Now.Year,2,20),
        new DateTime(DateTime.Now.Year,3,21),
        new DateTime(DateTime.Now.Year,4,21),
        new DateTime(DateTime.Now.Year,12,31)  };

    static public string Sign(DateTime inDate)
    {
       return SignList.Zip(startDates, (s, d) => new { sign = s, date = d })
                      .Where(x => (inDate.Month*100)+inDate.Day <= (x.date.Month*100)+x.date.Day)
                      .Select(x => x.sign)
                      .First();
    }
}

重新考虑(首先上面的例子更清楚)

public class Signs
{
  static List<string> SignList = new List<string>() {
    "Capricorn", "Aquarius", "Pisces", "Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo", "Libra", "Scorpio", "Sagittarius", "Capricorn", "Not Found" };

  static List<int> startDates = new List<int>() {
    // month * 100 + day of month
     120, 219, 320, 420, 521, 621, 722, 821, 923, 1023, 1122, 1222, 1232, 9999 // edge marker
  };

  static public string Sign(DateTime inDate)
  {
    return SignList[startDates.TakeWhile(d => (inDate.Month*100)+inDate.Day > d).Count()];
  }
}

答案 1 :(得分:7)

为什么你特别想要一个阵列?当然,更复杂的数据结构有助于封装功能,并帮助您将剩余的代码与其工作原理隔离开来,并且还可以让您考虑将来更精细的日期变化的细微变化。如果你想做那一年。

例如:

public class SO23182879
{
    public enum StarSign
    {
        Aquarius, Pisces, Aries, Taurus, Gemini, Cancer,
        Leo, Virgo, Libra, Scorpio, Sagittarius, Capricorn
    };
    static DateTime[] starSignStartDates = new DateTime[]
    {
        new DateTime(DateTime.Now.Year, 1, 20),
        new DateTime(DateTime.Now.Year, 2, 19),
        new DateTime(DateTime.Now.Year, 3, 21),
        new DateTime(DateTime.Now.Year, 4, 20),
        new DateTime(DateTime.Now.Year, 5, 21),
        new DateTime(DateTime.Now.Year, 6, 21),
        new DateTime(DateTime.Now.Year, 7, 23),
        new DateTime(DateTime.Now.Year, 8, 23),
        new DateTime(DateTime.Now.Year, 9, 23),
        new DateTime(DateTime.Now.Year, 10, 23),
        new DateTime(DateTime.Now.Year, 11, 22),
        new DateTime(DateTime.Now.Year, 12, 22),
        new DateTime(DateTime.Now.Year, 1, 20),
    };
    private class StarSignDateRange
    {
        public StarSign Sign { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
    }
    private List<StarSignDateRange> signStartDates = new List<StarSignDateRange>();

    public SO23182879()
    {
        int date = 0;
        foreach (StarSign sign in Enum.GetValues(typeof(StarSign)))
        {
            signStartDates.Add(new StarSignDateRange
            {
                Sign = sign,
                StartDate = starSignStartDates[date],
                EndDate = starSignStartDates[date + 1]
            });
            ++date;
        }
    }

    public StarSign Sign(DateTime date)
    {
        return signStartDates.First(
            sd => date.Month == sd.StartDate.Month && date.Day >= sd.StartDate.Day ||
                  date.Month == sd.EndDate.Month && date.Day < sd.EndDate.Day
                                   ).Sign;
    }

    public void Test()
    {
        IList<DateTime> testDates = new List<DateTime>
        {
            new DateTime(2014,1,1),
            new DateTime(2014,1,19),
            new DateTime(2014,1,20),
            new DateTime(2014,4,19),
            new DateTime(2014,4,20),
            new DateTime(2014,12,21),
            new DateTime(2014,12,22),
            new DateTime(2014,12,31),
        };
        foreach (DateTime d in testDates)
            Console.WriteLine(string.Format("{0} is in {1}", d, Sign(d)));
    }
}

正如您所见,我已经完成了之前开始的代码,并为您添加了Test()方法,以确定边缘条件是否有效。我非常感谢霍根指出了零年零&#34;问题和其他类似问题&#34;陷阱&#34;在我之前的草图中。