2017-11-28 4 views
0

文字列形式を "h:m:s:f"からなるTimeSpanの文字列形式を生成しようとしています(時、分、秒の場合は最大2桁、0ミリ秒間は3桁です。時間軸の可能なすべての文字列時間形式を生成する

所望のフォーマット

HH:M:SS:MM:S

HH:MM:SS

H:M:S:

FF

時間FFF

など。

私は次の操作を実行しようとした再帰を使用しますが、私はそうするのに苦労してることをやろうとしている

//Key - minimum digits left 
//Value starting digits count 
private static Dictionary<char, KeyValuePair<int, int>> replacements = 
    new Dictionary<char, KeyValuePair<int, int>> 
    { 
     ['f'] = new KeyValuePair<int, int>(0, 3), 
     ['s'] = new KeyValuePair<int, int>(1, 2), 
     ['m'] = new KeyValuePair<int, int>(1, 2), 
     ['h'] = new KeyValuePair<int, int>(1, 2) 
    }; 
private static char[] chars = new[] { 'f', 's', 'm', 'h' }; 
private static string baseTemplate = @"hh\:mm\:ss\:fff"; 
static IEnumerable<string> GetFormats(string template, int startIndex = 0, int endIndex = 0, List<string> formats = null) 
{ 
    if (formats == null) 
    { 
     formats = new List<string>{template}; 
    } 
    string copyTemplate = template; 
    char currentChar = chars[startIndex]; 
    int indexToRemove = copyTemplate.IndexOf(currentChar); 
    for (int i = 0; i < replacements[currentChar].Value - replacements[currentChar].Key; i++) 
    { 
     copyTemplate = copyTemplate.Remove(indexToRemove, 1); 
     formats.Add(copyTemplate.TrimEnd('\\', '.', ':')); 
    } 
    if (startIndex == chars.Length - 1 && endIndex == chars.Length - 1) 
    { 
     return formats; 
    } 
    if (startIndex == 0) 
    { 
     return GetFormats(baseTemplate, endIndex + 1, endIndex + 1, formats); 
    } 
    return GetFormats(copyTemplate, startIndex - 1, endIndex, formats); 
} 

しかし、それが動作しているようですしない、私も作業を持っています基本的にループに使用して強引なソリューションであるバージョン:

private static List<string> GetFormats(List<string> separators) 
{ 
    List<string> formats = new List<string>(); 
    for (int i = 0; i < separators.Count; i++) 
    { 
     string format = string.Empty; 
     for (int hours = 1; hours <= 2; hours++) 
     { 
      format += "h"; 
      string hoursCopy = format; 
      format += @"\:"; 
      for (int minutes = 1; minutes <= 2; minutes++) 
      { 
       format += "m"; 
       string minutesCopy = format; 
       format += @"\:"; 
       for (int seconds = 1; seconds <= 2; seconds++) 
       { 
        format += "s"; 
        string secondsCopy = format; 
        format += [email protected]"\{separators[i]}"; 
        for (int miliseconds = 0; miliseconds <= 3; miliseconds++) 
        { 
         formats.Add(format.TrimEnd('\\', '.', ':')); 
         format += "f"; 
        } 
        format = secondsCopy; 
       } 
       format = minutesCopy; 
      } 
      format = hoursCopy; 
     } 
    } 
    return formats; 
} 

呼び出し:

GetFormats(new[] { ":" }) 

再帰メソッドを修正するにはどうすればよいですか?

+0

@mjwills私は、h、m:s:fで構成され、時間、分、秒で最大2桁、ミリ秒で0-3桁の制約*を含んでいます。これを行うと、 'TimeSpan.ParseExact'に一連のフォーマットを渡すことができます。現在のバージョンではすべての組み合わせが印刷されていませんが、ほとんどが欠落しています。 – Deadzone

+0

'System.Globalization.DateTimeFormatinfo.GetAllDateTimePatterns()'がより良い開始点になるかもしれません – Plutonix

+0

@Plutonixそれはかなり便利なはずですが、もっと簡単な方法があるはずだと思っていましたが、それでもやりたいことがあります。 – Deadzone

答えて

2

は賢明aleck、OPになろうとしていないが、これは私のチームによって解決するために必要な実世界の問題であれば、我々はそれをこのようにしてください:

static public List<string> GetFormats() 
{ 
    return new List<string> 
    { 
     @"h\:mm\:ss\.fff", 
     @"h\:mm\:ss\.ff", 
     @"h\:mm\:ss\.f", 
     @"h\:mm\:ss", 
     @"h\:mm", 
     @"hh\:mm\:ss\.fff", 
     @"hh\:mm\:ss\.ff", 
     @"hh\:mm\:ss\.f", 
     @"hh\:mm\:ss", 
     @"hh\:mm" 
    }; 
} 

は、これは、1つです紙面上で自明に解決できる時限問題。 (国際化との互換性など)何らかの規定がないと仮定すると、これを自動化する必要はありません。

あなたはそれを生成する(分または秒は、私は確かに見たことがない一桁、と表現することができると主張)を主張した場合、あなたはこのようなLINQのビットでそれを行うことができます。

using System; 
using System.Linq; 
using System.Collections.Generic; 

static public class ExtensionMethods 
{ 
    static public IEnumerable<string> AddPossibilities(this IEnumerable<string> input, string symbol, string prefix, int minLength, int maxLength) 
    { 
     return input 
      .SelectMany 
       (
        stringSoFar => 
         Enumerable.Range 
          (
           minLength, 
           maxLength-minLength+1 
          ) 
         .Select 
          (
           length => stringSoFar + 
            (
             length == 0 ? "" : prefix 
             + Enumerable.Range(0, length) 
              .Select(i => symbol) 
              .Aggregate((c, n) => c + n) 
            ) 
          ) 
       ); 
    } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     var results = new List<string> { "" }; //Empty to start 
     var list = results 
      .AddPossibilities("h", @"" , 1, 2) 
      .AddPossibilities("m", @"\:" , 1, 2) 
      .AddPossibilities("s", @"\:" , 1, 2) 
      .AddPossibilities("f", @"\." , 0, 3); 

     var timeSpan = new TimeSpan(0,1,2,3,4); 
     foreach (var s in list) 
     { 
      Console.WriteLine(timeSpan.ToString(s)); 
     } 
    } 
} 

出力:DotNetFiddle上

1:2:3 
1:2:3.0 
1:2:3.00 
1:2:3.004 
1:2:03 
1:2:03.0 
1:2:03.00 
1:2:03.004 
1:02:3 
1:02:3.0 
1:02:3.00 
1:02:3.004 
1:02:03 
1:02:03.0 
1:02:03.00 
1:02:03.004 
01:2:3 
01:2:3.0 
01:2:3.00 
01:2:3.004 
01:2:03 
01:2:03.0 
01:2:03.00 
01:2:03.004 
01:02:3 
01:02:3.0 
01:02:3.00 
01:02:3.004 
01:02:03 
01:02:03.0 
01:02:03.00 
01:02:03.004 

Click here for working code

+0

コメントに記載されているように、それらはアプリケーションで手作業で書かれますが、私はそれが解決するのが楽しい問題だと思ったので、解決策を探しています。 – Deadzone

+0

私は再帰的なアプローチを探していたが、私はこれを行うだろうと思う:) – Deadzone

関連する問題