The best I can figure is first mapping to a nested array where the first element is the object and the second is the computed property but that seems really messy. Thoughts?
The best I can figure is first mapping to a nested array where the first element is the object and the second is the computed property but that seems really messy. Thoughts?
(* assuming: val total_len : string -> int *)
List.reduce seq ~f:(fun a b ->
if (total_len a) > (total_len b) then a else b)
It's not necessary in this case, but fold is often a lot more useful than reduce. At least the way I think of it, the type of reduce is 'a list -> ('a -> 'a -> 'a) -> 'a, whereas the type of fold is 'a list -> init:'b -> ('b -> 'a -> 'b) -> 'b. The upside is that you can construct basically any type of thing you'd like, since 'b is a completely different type. The downside is that if 'a is different than 'b, you need some sort of initial value to give it.edit: Yes, this does require you to compute string length multiple times...but keep in mind that getting string length is very cheap in languages with good strings. (That is, basically everything except C's null-terminated strings.) 99% of the time it's not going not going to matter at all. If you do care, you can map to a tuple of (original_struct,total_len) and then do the reduce and then another map to get back to your original structure, or use a fold, as I mentioned, or write a (tail-)recursive function that does it in slightly fewer operations. (Although I don't think JS has tail-call optimizations, so that's probably a bad idea if you're doing it in JS.)
let precomp = List.map lst (fun el -> ((length el), el)) in
let get_max (l1, el1) (l2, el2) = el1 if l1 > l2 else el2 in
List.reduce lst get_max Yes, this does require you to compute string length multiple times...but keep in mind that getting string length is very cheap in languages with good strings. (That is, basically everything except C's null-terminated strings.)
Since this is a discussion about Haskell, too, I feel obliged to say that computing the length of a String type in Haskell is an O(n) operation, because String is really just type String = [Char]
i.e. a linked list of Char values.Typically, if you want performance out of strings in Haskell, you'll use the Text or ByteString types BUT the length operation of Data.Text is still O(n). Only ByteString offers
length :: ByteString -> Int
Which is O(1).reduce/fold is a very general and powerful tool. In general you want to use the most specific and least powerful solution you can get away with. This spares the reader some thinking, and in theory gives the compiler more leeway. Also with less power there's less room for error.
Here a combination of maximum (or maximumBy in Haskell) and map will give you what you are looking for.
_.reduce(arr, function(p1, p2) {
var len = p2.firstName.length + p2.lastName.length;
return (len > p1[1]) ? [p2, len] : p1;
},
[null, -1]); _.chain(people)
.sortBy(function(person) {
return person.firstName.length + person.lastName.length; })
.last()
.value() _(people).max(function(person) {
return person.firstName.length + person.lastName.length;
});An alternative if you don't like that would be having the maximum-finding function receive an additional comparator argument, similarly to qsort.
Yup, though one small thing: it's 'Schwartzian transform'[1] for Randal Schwartz.
(argmax (λ(c) (string-length (customer-name c)))
customers)
http://docs.racket-lang.org/reference/pairs.html?q=argmax#(d...)Haskell has argmaxBy: http://hackage.haskell.org/packages/archive/list-extras/0.3....
If your language doesn't have argmax, fold the list with the best value, like this in lisp:
(define (my-argmax fun lst)
(foldl (λ(prev-max elt)
(if (< (fun prev-max) (fun elt))
elt
prev-max))
(car lst)
(cdr lst)))
No extra space usage, no temporary values, no sorting; all in O(N) time. :) longestName = maximumBy . comparing $ \(f,l) -> length $ f++lIf you absolutely insist on map/reduce, you can just use reduce, where your binary function returns whichever object has a longer full name.
longestLastname :: [Person] -> Person
longestLastname names = maximumBy (comparing (length . lastname)) names
In general, you can do map something like extractProperty list = map (\x -> (f x, x)) list
Then work on the first element of the tuple (comparing for sorting etc), and at the end return the original object by extracting the second element of the tuple. people = [Person('foo', 'bar'), Person('John', 'Doe'), Person('Jane', 'Anonymous')]
key = lambda person: len(person.first_name + person.last_name)
max(people, key=key)