我有List
个
public class FriendList
{
public List<string> friends { get; set; } // List of friends names
public DateTime timestamp { get; set; } // date/time on the data file
}
我需要一个程序来获取timestamp
排序的前2个(然后用它们做一些其他的东西)。所以我开始写的是
public void CompareLastTwo ( )
{
if ( this._fhist.Count < 2 )
{
Console.WriteLine("Need at least two instances of Facebook profile data in the Data folder");
}
FriendList latest, secondLatest;
if ( this._fhist[0].timestamp > this._fhist[1].timestamp )
{
latest = this._fhist[0];
secondLatest = this._fhist[1];
}
else
{
latest = this._fhist[1];
secondLatest = this._fhist[0];
}
for ( int i = 2, n = this._fhist.Count; i < n; ++i )
{
if ( this._fhist[i].timestamp > latest.timestamp )
{
secondLatest = latest;
latest = this._fhist[i];
}
else if ( this._fhist[i].timestamp > secondLatest.timestamp && this._fhist[i].timestamp <= latest.timestamp )
{
secondLatest = this._fhist[i];
}
}
// ...
}
然后我通过查看How to get first N elements of a list in C#?我可以做到
来实现List<FriendList> latestTwoFriendLists = this._fhist.OrderBy(L => L.timestamp).Take(2);
哪个更紧凑,但 效率 ????或者,在Take
第一个2之前,计算方程右侧的过程是否得到整个有序列表?
答案 0 :(得分:7)
OrderBy
请求第一项时, Take
会对整个集合进行排序。
因此,整个LINQ查询将是 O(n * log(n)),而不是 O(n),就像现有代码一样。
答案 1 :(得分:1)
一般来说,如果将OrderBy实现为惰性排序,则OrderBy不必对这种情况下的所有项进行排序。标准的linq排序不是懒惰的,所以它会排序一切。你的解决方案尽可能快,你会发现更好。只需将其作为独立功能进行清理,如下所示:
public class FriendList
{
public List<string> friends { get; set; } // List of friends names
public DateTime timestamp { get; set; } // date/time on the data file
}
public static Tuple<T, T> GetTwoBiggest<T>(IEnumerable<T> array, Comparison<T> comp)
{
var enumerator = array.GetEnumerator();
if (!enumerator.MoveNext()) { throw new ArgumentException("We need collection with at least two items"); }
T max1 = enumerator.Current;
if (!enumerator.MoveNext()) { throw new ArgumentException("We need collection with at least two items"); }
T max2 = enumerator.Current;
if (comp(max1, max2) < 0)
{
T tmp = max1;
max1 = max2;
max2 = tmp;
}
while (enumerator.MoveNext())
{
T actual = enumerator.Current;
if (comp(actual, max1) > 0)
{
max2 = max1;
max1 = actual;
}
else if (comp(actual, max2) > 0)
{
max2 = actual;
}
}
return new Tuple<T, T>(max1, max2);
}
private void button6_Click(object sender, EventArgs e)
{
List<FriendList> list = new List<FriendList>()
{
new FriendList() { timestamp = new DateTime(2015,1,1) },
new FriendList() { timestamp = new DateTime(2015,10,2) },
new FriendList() { timestamp = new DateTime(2015,5,3) },
new FriendList() { timestamp = new DateTime(2015,2,4) },
new FriendList() { timestamp = new DateTime(2015,3,5) },
new FriendList() { timestamp = new DateTime(2015,7,6) },
new FriendList() { timestamp = new DateTime(2015,11,7) },
new FriendList() { timestamp = new DateTime(2015,8,8) },
};
var twoBiggest = GetTwoBiggest(list, (a, b) => a.timestamp.CompareTo(b.timestamp));
Console.WriteLine(twoBiggest.Item1.timestamp);
Console.WriteLine(twoBiggest.Item2.timestamp);
}