2014-04-20 75 views
3

我正在解決以下問題:用日期和星座填充二維數組的更好方法

我想填充一個二維[365,2]數組。第一個值應該保留日期:從1月1日開始到12月31日結束。第二個值應該在每個日期保存相應的星座:

例如, 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月份爲白羊座的部分稱呼一次,在一月份爲白羊座的部分稱呼一次)來繞過月份休息問題。

此解決方案的工作原理,但它似乎令人難以置信的粗糙,我。

任何人都可以給我一些更優雅的解決方案的指針嗎?

+3

什麼是你原來的問題?那就是,你爲什麼試圖填充這個數組?看來你可能會過度複雜化。 –

+0

我確實是過分複雜的原始問題:),但我仍想知道如何有效處理這個問題。 – Fang

+0

您是否特別需要使用數組作爲數據結構?或者就像你想象的那樣? – ClickRick

回答

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()]; 
    } 
} 
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()方法給你看,邊緣工作條件。我很感謝霍根指出我早期草圖中的「零年」問題和其他類似的「陷阱」。

+0

是的,我寫了,並做了一些Google搜索 - 我已經刪除它。很好的答案,從我的+1。 – Hogan

+0

欣賞努力!本週晚些時候會做比較。 – Fang