0

次のようなファイルがあります(リストはソートされています):

2013-05-02 07:45:15
2013-05-02 09:25:01
2013-05-02 18:15:15
2013-05-04 08:45:15
2013-05-04 17:45:35

そのリストで毎日最初と最後の時間だけを取得したいので、これを取得したいということです:

2013-05-02 07:45:15
2013-05-02 18:15:15
2013-05-04 08:45:15
2013-05-04 17:45:35

これを達成するための最も効率的な方法は何でしょうか? サイクルを使用してこれを取得し、その中で日付を比較できると思います。しかし、もっと効率的な方法があるのではないでしょうか? これは、linqまたはサイクルを使用するよりも速く/きれいな方法で結果を得ることができる他のものを使用して達成できますか?

4

7 に答える 7

1

日付でグループ化し、各日付の最初と最後の行を取得します。例:

string[] dates = {
  "2013-05-02 07:45:15",
  "2013-05-02 09:25:01",
  "2013-05-02 18:15:15",
  "2013-05-04 08:45:15",
  "2013-05-04 17:45:35"
};

var days =
  dates.GroupBy(s => s.Substring(0, 10))
  .Select(g => new { First = g.First(), Last = g.Last() });

foreach (var day in days) {
 Console.WriteLine("{0} - {1}", day.First, day.Last);
}

出力:

2013-05-02 07:45:15 - 2013-05-02 18:15:15
2013-05-04 08:45:15 - 2013-05-04 17:45:35
于 2013-06-10T08:14:11.087 に答える
0
    static void Main(string[] args)
    {
        var dates = System.IO.File.ReadAllLines(@"C:\dates.txt").Select(o => DateTime.Parse(o));
        var res = new List<DateTime>();
        foreach (var item in (from o in dates group o by o.Date into g select g.Key))
        {
            var dummy = dates.Where(o => o.Date == item);
            res.Add(dummy.Max());
            res.Add(dummy.Min());
        }

    }
于 2013-06-10T08:13:48.577 に答える
0

日付を日ごとにグループ化し、グループの内容を並べ替えて、最初と最後の要素を取得できます。

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

class Program {
    static void Main(string[] args) {

        string[] fileContents = new string[] { 
                "2013-05-02 07:45:15",
                "2013-05-02 09:25:01",
                "2013-05-02 18:15:15",
                "2013-05-04 08:45:15",
                "2013-05-04 17:45:35"
            };
        List<DateTime> dates = fileContents.ToList().ConvertAll(s => DateTime.ParseExact(s, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture));
        foreach (var datesInSameDay in dates.GroupBy(d => d.Day)) {
            var datesList = datesInSameDay.ToList();
            datesList.Sort();
            Console.WriteLine(datesList.First());
            Console.WriteLine(datesList.Last());
        }
    }
}
于 2013-06-10T08:13:59.297 に答える
0

最新の日付を取得するには、次を使用できます。

var latestDate = datetimeCollection.Max();

そして最も古いものの場合:

var oldestDate = datetimeCollection.Min();

オブジェクトdatetimeCollectionのリスト/コレクションであることに注意してください。DateTime

于 2013-06-10T08:08:45.787 に答える
0

「これを達成するための最も効率的な方法は何ですか?」

リストがソートされていると言うので、ソース時間の 1 回のパスで必要な時間を生成できます。

これにより、他のすべての回答によって行われるグループ化が回避されます。入力データがソートされていない場合は、このようなグループ化が必要になりますが、日付/時刻の昇順でソートされているため明示的にグループ化する必要はありません。

まず、文字列を に変換する単純なコンバーターを定義しましょうDateTime

public IEnumerable<DateTime> ParseTimes(IEnumerable<string> times)
{
    return times.Select(time => DateTime.ParseExact(time, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture));
}

次に、次のように、毎日の最初と最後の時間 (または、その日に 1 回しか指定されていない場合はその日の唯一の時間) を返す単純なメソッドを作成できます。

public IEnumerable<DateTime> FirstAndLastTimesForEachDay(IEnumerable<DateTime> times)
{
    DateTime previous = DateTime.MinValue;
    DateTime current  = DateTime.MinValue;

    foreach (var time in times)
    {
        if (previous.Date < time.Date)
        {
            if (previous != current)
                yield return previous;

            yield return time;

            current = time;
        }

        previous = time;
    }

    if (previous != current)
        yield return previous;
}

次に、次のように使用できます。

var times = new []
{
    "2013-05-02 07:45:15",
    "2013-05-02 09:25:01",
    "2013-05-02 18:15:15",
    "2013-05-03 12:34:45",
    "2013-05-04 08:45:15",
    "2013-05-04 17:45:35",
    "2013-05-05 20:00:00"
};

foreach (var time in FirstAndLastTimesForEachDay(ParseTimes(times)))
    Console.WriteLine(time);

上記の実装では、DateTime が 1 つしか含まれていない日には、DateTime が 1 つしか出力されないことに注意してください。代わりに、1 日に発生する 1 つの DateTime の 2 倍を出力に含める場合 (つまり、時刻が同じであっても、1 日あたりの DateTime のペアは常に存在します)、実装を次のように変更します。

public IEnumerable<DateTime> FirstAndLastTimesForEachDay(IEnumerable<DateTime> times)
{
    DateTime previous = DateTime.MinValue;

    foreach (var time in times)
    {
        if (previous.Date < time.Date)
        {
            if (previous != DateTime.MinValue)
                yield return previous;

            yield return time;
        }

        previous = time;
    }

    if (previous != DateTime.MinValue)
        yield return previous;
}
于 2013-06-10T08:51:49.320 に答える