Весь Windows APIs думает в UTF-16, таким образом, Вы - более обеспеченная запись обертки вокруг Вашей библиотеки, которая преобразовывает на границах.
Достаточно странно, Windows думает, что UTF-8 является кодовой страницей в целях преобразования, таким образом, Вы используете те же API, как Вы были бы для преобразования между кодовыми страницами:
std::wstring Utf8ToUtf16(const char* u8string)
{
int wcharcount = strlen(u8string);
wchar_t *tempWstr = new wchar_t[wcharcount];
MultiByteToWideChar(CP_UTF8, 0, u8string, -1, tempWstr, wcharcount);
wstring w(tempWstr);
delete [] tempWstr;
return w;
}
И что-то вроде подобной формы для преобразования назад.
У нас есть метод расширения , чтобы сделать это в MoreLINQ . Вы можете посмотреть на реализацию там, но в основном это случай перебора данных, запоминания максимального элемента, который мы видели до сих пор, и максимального значения, полученного им в рамках проекции.
В вашем случае вы бы что-то сделали например:
var item = items.MaxBy(x => x.Height);
Это лучше (IMO), чем любое из представленных здесь решений, кроме второго решения Мердада (которое в основном совпадает с MaxBy
):
Max
значение, а затем найти первый элемент с этим значением O (n), но повторяет последовательность дважды. По возможности следует использовать LINQ в однопроходном режиме. Это потребует сортировки (O (n log n)), но это очень просто и гибко. Еще одно преимущество - возможность использовать его с LINQ to SQL:
var maxObject = list.OrderByDescending(item => item.Height).First();
Обратите внимание, что это дает преимущество перечисления последовательности list
только один раз. Хотя это может не иметь значения, если list
является List
, который за это время не меняется, это может иметь значение для произвольных объектов IEnumerable
. Ничто не гарантирует, что последовательность не изменится в разных перечислениях, поэтому методы, которые делают это несколько раз, могут быть опасными (и неэффективными, в зависимости от характера последовательности). Тем не менее, это все еще далеко не идеальное решение для больших последовательностей. Я предлагаю написать собственное расширение MaxObject
вручную, если у вас есть большой набор элементов, чтобы можно было сделать это за один проход без сортировки и прочего (O (n)):
static class EnumerableExtensions {
public static T MaxObject<T,U>(this IEnumerable<T> source, Func<T,U> selector)
where U : IComparable<U> {
if (source == null) throw new ArgumentNullException("source");
bool first = true;
T maxObj = default(T);
U maxKey = default(U);
foreach (var item in source) {
if (first) {
maxObj = item;
maxKey = selector(maxObj);
first = false;
} else {
U currentKey = selector(item);
if (currentKey.CompareTo(maxKey) > 0) {
maxKey = currentKey;
maxObj = item;
}
}
}
if (first) throw new InvalidOperationException("Sequence is empty.");
return maxObj;
}
}
и используйте его с:
var maxObject = list.MaxObject(item => item.Height);
Выполнение заказа с последующим выбором первого элемента - это напрасная трата времени на размещение элементов после первого. Вам не важен их порядок.
Вместо этого вы можете использовать агрегатную функцию, чтобы выбрать лучший элемент на основе того, что вы ищете.
var maxHeight = dimensions
.Aggregate((agg, next) =>
next.Height > agg.Height ? next : agg);
var maxHeightAndWidth = dimensions
.Aggregate((agg, next) =>
next.Height >= agg.Height && next.Width >= agg.Width ? next: agg);
Я считаю, что сортировка по столбцу, для которого вы хотите получить максимальное значение, а затем захват первого, должна работать. Однако, если имеется несколько объектов с одинаковым значением MAX, будет захвачен только один:
private void Test()
{
test v1 = new test();
v1.Id = 12;
test v2 = new test();
v2.Id = 12;
test v3 = new test();
v3.Id = 12;
List<test> arr = new List<test>();
arr.Add(v1);
arr.Add(v2);
arr.Add(v3);
test max = arr.OrderByDescending(t => t.Id).First();
}
class test
{
public int Id { get; set; }
}