2010-01-07 5 views
4

У меня есть список списков.Как отсортировать этот список?

List<List<T>> li = { 
    {a1,a2,a3 ... aN}, 
    {b1,b2,b3 ... bN}, 
    ... 
}; 

double foo(List<T> list) 
{ 
    // do something 
    // e.g {1,2,3} 
    // it = 1 + 2 + 3 

    return it; 
} 

Теперь я хочу, чтобы отсортировать li таким образом, что чем выше foo(x) для x выше она должна появиться в отсортированном списке.

Каков наилучший способ использования C#/Python/любых других языков?

+0

Почему вы показываете C# и спрашивает о Python? Как Python входит в этот вопрос? –

+0

@S. Lott Я сейчас кодирую C#, но я также хотел бы знать, как это сделать в Python, так как это мой любимый язык! –

+0

Теперь, когда моя основная цель подана, это может быть и кодовый гольф! –

ответ

10

С немного LINQ:

var q = from el in li 
     orderby foo(el) 
     select el; 
li = q.ToList(); 
+0

+ 1A Это он !!! –

+0

Как сделать обратную сортировку в LINQ? –

+3

'orderby foo (el) по убыванию' –

0

Для этого вы можете адаптировать любую из популярных процедур сортировки. Просто используйте foo (x) для сравнения, а не x.

+0

Я не хочу сортировать технику. Я хочу способ выразить это эффективно на языке. –

5

Это путь Python: Просто передать функцию в качестве key аргумента sorted() или .sort():

>>> mylist = [123, 765, 4, 13] 
>>> def mod5(x): 
...  return x%5 
... 
>>> sorted(mylist, key = mod5) 
[765, 123, 13, 4] 
>>> sorted(mylist, key = mod5, reverse = True) 
[4, 123, 13, 765] 
+0

+1 Фантастический !!! Почему я не могу принять 2 ans ??? –

+0

Это прекрасно :-) Решение C# помогло вам больше всего, поэтому вы приняли правильное решение. – balpha

+0

Является ли это функциональным способом программирования ??? просто любопытно;) –

10

Решение Haskell особенно элегантна с комбинатором on из Data.Function.

import Data.Function (on) 
import Data.List (sortBy) 

lists = [ [ 5, 6, 8 ] 
     , [ 1, 2, 3 ] 
     ] 

main = do 
    print $ sortBy (compare `on` foo) lists 
    where 
    foo = sum 

Выход:

[[1,2,3],[5,6,8]]

Там также comparing из Data.Ord, что позволяет нам вместо того, чтобы писать

main = do 
    print $ sortBy (comparing foo) lists 
    where 
    foo = sum 

The definition of comparing является прямым

comparing :: (Ord a) => (b -> a) -> b -> b -> Ordering 
comparing p x y = compare (p x) (p y) 

но мы могли бы также определить его с точки зрения on:

comparing :: (Ord b) => (a -> b) -> a -> a -> Ordering 
comparing f = compare `on` f 

или полностью точка бесплатно

comparing :: (Ord b) => (a -> b) -> a -> a -> Ordering 
comparing = (compare `on`) 

Haskell манипулирует функции так сильно, как Perl манипулирует строки.

+2

Или используйте 'sortWith': http://www.haskell.org/ghc/docs/latest/html/libraries/base/GHC-Exts.html#v%3AsortWith – ephemient

+1

Должен заметить, что цель' sortWith' на самом деле не просто быть ярлыком для 'sortBy. сравнение', но на самом деле обеспечить тонкости для обобщенного понимания списка: '{- # LANGUAGE TransformListComp # -} [list | list <- lists, then sortWith by sum list] ' – ephemient

1

Любой другой язык?Хорошо, вот некоторые F #:

Пример: сортировка по сумме:

let foo = List.sum 
let li = [[1;2];[42;1];[3;4]] 

let result = li |> List.sortBy (fun el -> foo el) 

Результат (F # интерактивный):

val result : int list list = [[1; 2]; [3; 4]; [42; 1]] 

Golfed:

let result = li |> List.sortBy (fun el -> foo el) 
//shorter 
let res = li |> List.sortBy foo 
//evn shrtr 
let r=List.sortBy foo li 

C# версия:

var result = li.OrderBy(el=>el.Sum()); 
1

в Эрл:

-module (codegolfs). 
-export ([sortmain/0]). 

sortmain() -> 
    sort( 
    fun (SubList) -> lists:sum(SubList) end, 
    [ [1,2,3],[1,3],[2,5,6] ]). 
    % output: [[2,5,6],[1,2,3],[1,3]] 

sort(Fun,List) -> 
    lists:sort(fun(A,B) -> Fun(A) < Fun(B) end,List). 
2

Рубина:

mylist = [[1,2,3], 
      [3,5,9], 
      [1,1,1], 
      [10,23,14]] 

sortedlist = mylist.sort {|a,b| b.inject {|sum, n| sum + n } <=> a.inject {|sum,n| sum + n}} 

Я не уверен, что правила Co Go, и я не написать метод Foo, но сумма может легко произойти в обув ,

Мой тестовый выход:

puts sortedlist.inspect 

[[10, 23, 14], [3, 5, 9], [1, 2, 3], [1, 1, 1]]

+2

Вы также можете сделать' li = li.sort_by {| i | foo (i)} .reverse', если производительность не имеет большого значения. – kejadlen

2

В Perl это часто делается с помощью известного Schwartzian transform.

use List::Util qw(sum); 
@li = map {$$_[0]} sort {$$a[1] <=> $$b[1]} map {[$_, sum(@$_)]} @li; 

Повторное использование Sort::Key все же.

use List::Util qw(sum); 
use Sort::Key qw(nkeysort); 
@li = nkeysort {sum(@$_)} @li; 
+0

Конечно, наивное выражение '@li = sort {sum (@ $ a) <=> sum (@ $ b)} @ li' тоже работает, эффективность торговли для краткости. – ephemient

0

Tcl:

proc foo nums {tcl::mathop::+ {*}$nums} 
set l {{1 2 3} {4 5 6} {3} {42 -40}} 
lsort -command {apply {{a b} {expr {[foo $a] - [foo $b]}}}} $l 
# => {42 -40} 3 {1 2 3} {4 5 6} 
1

Ruby (бесстыдно копирование входных данных Beanish компании):

list = [ 
    [1, 2, 3], 
    [3, 5, 9], 
    [1, 1, 1], 
    [10, 23, 14] 
] 

p list.sort_by { |a| -a.inject(&:+) } 
# => [[10, 23, 14], [3, 5, 9], [1, 2, 3], [1, 1, 1]] 
1

Clojure:

(let [lst '((1 2 3) (3 5 9) (1 1 1) (10 23 14))] 
(sort #(> (foo %1) (foo %2)) lst)) 
Смежные вопросы