2012-03-20 20 views
19

このような配列で:coffeescriptで配列をソートするにはどうすればよいですか?

users = [ 
    { id: 1, fname: 'Fred', lname: 'Flinstone', state: 'CA' }, 
    { id: 2, fname: 'George', lname: 'Winston', state: 'FL' }, 
    { id: 3, fname: 'Luke', lname: 'Skywalker', state: 'CA' } 
] 

、あなたがCoffeeScriptので姓でソートしたい、あなたがこれを行うことができます:

users.sort (a,b) -> 
    return if a.lname.toUpperCase() >= b.lname.toUpperCase() then 1 else -1 

私はこのような機能を使用してみました:

sortBy = (field, reverse, primer) -> 
    key = (x) -> 
     return if primer? then primer x[field] else x[field] 
    return (a,b) -> 
     A = key a 
     B = key b 
     return (A < B ? -1 : (A > B ? 1 : 0)) * [1,-1][+!!reverse] 

このように呼び出された:

users.sort sortBy "lname", false, (a) -> 
    return a.toUpperCase() 

しかし、それは配列を適切にソートしませんでした。

1つ以上のフィールドでソートする方法はありますか?つまり、最初に状態をソートし、次に姓でソートしますか?私は上記の "sortBy"機能を改良し、少なくとも2つのフィールドでソートする機能を追加したいと考えていました。

+2

が事のどんなものより「より良い」かもしれない?見つかったより一般的な例に基づいて

sortByLowercase: (collection, key) -> collection.sort (a, b) -> [av, bv] = [a[key], b[key]] [av, bv] = [av.toLowerCase(), bv.toLowerCase()] if av >= bv then 1 else if av <= bv then -1 else 0 sortByLowercase(users,'lname') 

(実際はソートを安定に保つために '<='ではなく '<'を使用します) – Pointy

+3

これはJSONではありません。 –

+0

三項演算子を使用することができます: 'return a.lname.toUpperCase()> b.lname.toUpperCase()? 1:-1' –

答えて

20

簡単な方法があります。ちょうどあなたの一般ソート機能を再利用、および||を使用してそれらを連結:

sortBy = (key, a, b, r) -> 
    r = if r then 1 else -1 
    return -1*r if a[key] > b[key] 
    return +1*r if a[key] < b[key] 
    return 0 

users.sort (a,b) -> 
    sortBy('id', a, b, true) or 
    sortBy('lname', a, b) or 
    sortBy('fname', a, b) 

機能が安いです。

sortByMultiple = (a, b, keys) -> 
    return r if (r = sortBy key, a, b) for key in keys 
    return 0 

users.sort (a,b) -> sortByMultiple a, b, ['id', 'lname', 'fname'] 

しかし、その後、あなたはそれらのそれぞれに順番または他のパラメータを設定する機能を失う:あなたは、そのための抽象化を構築することができます。

+0

です。本当に滑らかです。私は 'または'がどのように機能を連鎖させるかを理解しようとしています。前の値が '0'の場合、次のsortyBy関数に移動するだけなので、それはありますか?あるいは、別の方法としては、最初のキーが満たされる(つまり「0」)までソートしてから次のキーに移動することですか? – jiy

+0

orBを使ってsortBy関数を連鎖させてテストしたことが素晴らしい! sortByMultipleをミックスに投げても成功しなかったが、何も正しくソートされなかった。非常に有益な答えをありがとう! – jiy

+0

@jiyはい、それはかなりです。基準の1つがゼロ以外の値を返すまで続けてください。 –

15

また、あなたはそれを自分で実装する必要がないようにUnderscoresortByを使用して検討する必要があります

_(users).sortBy (u) -> [u.state, u.lname.toUpperCase()] 
+0

ありがとう!それは非常に有望ですね。正確に私が探していたもの – jiy

+0

答えのリンクはもう存在しません。http://underscorejs.org/とhttp://underscorejs.org/#sortByは新しいリンク –

3

これは、lodashを使用するとデフォルトで実装されていたと思われるものですが、そうではありません。

だからここにいる!私はhere