Daily Challenge #26 - Ranking Position dev.to staff on July 29, 2019 We're back with another week of challenges! Today, let's get a little creative and develop a ranking system where we can sort points and calculat... Read full post Submit Preview Dismiss Collapse Expand Alvaro Montoro Alvaro Montoro Alvaro Montoro Follow CSS aficionado ⊆ Web Developer ⊆ Software Developer ⊆ Person (He/Him) Location Austin, TX Work UI Manager / CSS Aficionado Joined Apr 27, 2019 • Jul 29 '19 Dropdown menu Copy link Hide JavaScript const addRanking = list => { let prevValue = undefined; let prevRanking = 1; list.sort((a,b) => { if (a.points === b.points) { if (b.name > a.name) { return -1; } else { return 1; } } else { return b.points - a.points; } }).forEach((el, idx) => { if (prevValue === el.points) { el.ranking = prevRanking; } else { el.ranking = idx + 1; prevValue = el.points; prevRanking = el.ranking; } }); }; Enter fullscreen mode Exit fullscreen mode Live demo on Codepen. Collapse Expand Alvaro Montoro Alvaro Montoro Alvaro Montoro Follow CSS aficionado ⊆ Web Developer ⊆ Software Developer ⊆ Person (He/Him) Location Austin, TX Work UI Manager / CSS Aficionado Joined Apr 27, 2019 • Jul 29 '19 Dropdown menu Copy link Hide This could be considerably reduced by using ternary operators. Collapse Expand nishu1343 nishu1343 nishu1343 Follow Im a developer.want to learn more about front end and backend development through this platform Location Virginia Work Mid .Net developer at Accenture Joined Dec 25, 2019 • Jul 21 '20 Dropdown menu Copy link Hide Hi alvaro. Could u please explain what u did in this program by putting comments in ur codepen link. Im trying to understand😊 Alvaro Montoro Alvaro Montoro Alvaro Montoro Follow CSS aficionado ⊆ Web Developer ⊆ Software Developer ⊆ Person (He/Him) Location Austin, TX Work UI Manager / CSS Aficionado Joined Apr 27, 2019 • Jul 21 '20 Dropdown menu Copy link Hide I updated the Codepen with comments. Let me know if more details are needed. nishu1343 nishu1343 nishu1343 Follow Im a developer.want to learn more about front end and backend development through this platform Location Virginia Work Mid .Net developer at Accenture Joined Dec 25, 2019 • Jul 21 '20 Dropdown menu Copy link Hide Thanku alvaro😊 Collapse Expand Avalander Avalander Avalander Follow "Biography is irrelevant" - Seven of nine (probably) if she was asked that question. Joined Mar 12, 2018 • Jul 31 '19 • Edited on Jul 31 • Edited Dropdown menu Copy link Hide My solution in clumsy Haskell: -- Data/Score.hs module Data.Score where data Score = Score { name :: String , points :: Int } deriving (Show) compare_scores :: Score -> Score -> Ordering compare_scores a b = case compare (points a) (points b) of EQ -> compare (name b) (name a) LT -> LT GT -> GT -- Data/Rank.hs module Data.Rank where import Data.Score as S data Rank = Rank { name :: String , points :: Int , position :: Int } deriving (Show) from_score :: S.Score -> Int -> Rank from_score score position = Rank { Data.Rank.name = S.name score , Data.Rank.points = S.points score , Data.Rank.position = position } import Data.List (sortBy) import Data.Rank as R import Data.Score as S sort_scores :: [ S.Score ] -> [ S.Score ] sort_scores = sortBy (flip S.compare_scores) map_to_records :: [ S.Score ] -> [ R.Rank ] map_to_records = foldl kevin [] where kevin :: [ R.Rank ] -> S.Score -> [ R.Rank ] kevin [] score = [ R.from_score score 1 ] kevin xs score | tied_score = xs ++ [ R.from_score score prev_position ] | otherwise = xs ++ [ R.from_score score next_position ] where prev = last xs tied_score = R.points prev == S.points score prev_position = R.position prev next_position = (length xs) + 1 rank_scores :: [ S.Score ] -> [ R.Rank ] rank_scores = map_to_records . sort_scores scores :: [ S.Score ] scores = [ S.Score { S.name = "John" , S.points = 100 } , S.Score { S.name = "Bob" , S.points = 130 } , S.Score { S.name = "Mary" , S.points = 120 } , S.Score { S.name = "Kate" , S.points = 120 } ] rank_scores scores {-[ Rank {name = "Bob", points = 130, position = 1} , Rank {name = "Kate", points = 120, position = 2} , Rank {name = "Mary", points = 120, position = 2} , Rank {name = "John", points = 100, position = 4} ] -} Collapse Expand E. Choroba E. Choroba E. Choroba Follow Perl enthusiast. Location Prague, EU Education Master in Logic, PhD in Mathematical Linguistics Work Researcher at Charles University Joined Feb 13, 2018 • Jul 29 '19 • Edited on Jul 29 • Edited Dropdown menu Copy link Hide Going functional in Perl: #!/usr/bin/perl use warnings; use strict; sub rank { my ($in) = @_; my $i = 1; my $same = 0; my $last = 'INF'; [ map { if ($_->{points} == $last) { ++$same; } else { $i += $same; $last = $_->{points}; $same = 1; } +{ %$_, position => $i } } sort { $b->{points} <=> $a->{points} || $a->{name} cmp $b->{name} } @$in ] } my $input = [ { name => "John", points => 100 }, { name => "Bob", points => 130 }, { name => "Mary", points => 120 }, { name => "Kate", points => 120 }]; my $expected = [ { name => "Bob", points => 130, position => 1 }, { name => "Kate", points => 120, position => 2 }, { name => "Mary", points => 120, position => 2 }, { name => "John", points => 100, position => 4 }]; use Test::More tests => 1; is_deeply rank($input), $expected; Collapse Expand Hao Hao Hao Follow I do code... and stuff Location Yokohama Work Working as Something at Somewhere Joined Jun 12, 2019 • Jul 30 '19 • Edited on Jul 30 • Edited Dropdown menu Copy link Hide There's probably a better way which requires only one iteration? const players = [ { name: "John", points: 100, }, { name: "Bob", points: 130, }, { name: "Mary", points: 120, }, { name: "Kate", points: 120, }, ]; players.sort((a, b) => { return (a.points == b.points ? a.name > b.name : a.points < b.points) || -1; }).forEach((e, i, arr) => { e.rank = i && arr[i-1].points == e.points ? arr[i-1].rank : i + 1; }); console.log(players); // [{"name":"Bob","points":130,"rank":1},{"name":"Kate","points":120,"rank":2},{"name":"Mary","points":120,"rank":2},{"name":"John","points":100,"rank":4}] Collapse Expand Ceck Ceck Ceck Follow Joined Jul 16, 2019 • Aug 1 '19 Dropdown menu Copy link Hide i want to contribute my idea with your code. i hope u enjoy with that. Maybe it's shoter players.sort((a, b) => { return (a.points == b.points ? a.name > b.name : a.points < b.points) || -1; }).map((e,i)=>({...e,position:(i+1)})) Collapse Expand willsmart willsmart willsmart Follow Coding since 11yo, that makes it over 30 years now ~~~ Have a PhD in Comp Sci ~~~ Love to go on bike tours ~~~ I try to stay as generalist as I can in this crazy wide place coding is at now. Location NZ Education to post-doc Joined Mar 28, 2019 • Jul 30 '19 • Edited on Jul 30 • Edited Dropdown menu Copy link Hide Just a short one in Javascript Edit: somehow I hadn't noticed the position bit 😳, so I've added that as a map call. ranked = players => players .slice() .sort((a, b) => Math.sign(b.points - a.points) * 2 + a.name.localeCompare(b.name)) .map((item, index, array) => Object.assign(item, { position: index && item.points == array[index - 1].points ? array[index - 1].position : index + 1, }) ); players = [ {name: 'b', points: 1}, {name: 'b', points: 3}, {name: 'b', points: 2}, {name: 'a', points: 2}, {name: 'c', points: 2} ]; console.log(JSON.stringify(ranked(players),null,2)); /* ^ [ { "name": "b", "points": 3, "position": 1 }, { "name": "a", "points": 2, "position": 2 }, { "name": "b", "points": 2, "position": 2 }, { "name": "c", "points": 2, "position": 2 }, { "name": "b", "points": 1, "position": 5 } ] */ Collapse Expand La blatte La blatte La blatte Follow Joined May 2, 2019 • Jul 30 '19 • Edited on Jul 30 • Edited Dropdown menu Copy link Hide Here it goes! const players = [ { name: "John", points: 100, }, { name: "Bob", points: 130, }, { name: "Mary", points: 120, }, { name: "Kate", points: 120, }, ]; const sortPlayers = (arr) => arr.sort((a, b) => b.points - a.points || a.name.localeCompare(b.name) ) .map((p, i, l) => Object.assign(p, {position: i && !(l[i-1].points-p.points) ? l[i-1].position : i+1})); And the result: sortPlayers(players); [ { "name": "Bob", "points": 130, "position": 1 }, { "name": "Kate", "points": 120, "position": 2 }, { "name": "Mary", "points": 120, "position": 2 }, { "name": "John", "points": 100, "position": 4 } ] Collapse Expand Mat-R-Such Mat-R-Such Mat-R-Such Follow Joined Jan 8, 2020 • Apr 9 '20 Dropdown menu Copy link Hide Python r=[ { 'name': "John", 'points': 100, }, { 'name': "Bob", 'points': 130, }, { 'name': "Mary", 'points': 120, }, { 'name': "Kate", 'points': 120, }, ] def points(e): return e['points'] p=1 r.sort(reverse= True , key=points) p_max=r[0]['points'] r[0]['position']= p for i in range(1,len(r)): if r[i]['points'] == p_max: r[i]['position']= p else: p+=1 p_max=r[i]['points'] r[i]['position']=p print(r) Collapse Expand SavagePixie SavagePixie SavagePixie Follow Always learning new things. I love web development and coding in general. Joined Jul 23, 2019 • Jul 29 '19 Dropdown menu Copy link Hide Shouldn't John's position in the example be 3? Code of Conduct • Report abuse
JavaScript
Live demo on Codepen.
This could be considerably reduced by using ternary operators.
Hi alvaro. Could u please explain what u did in this program by putting comments in ur codepen link. Im trying to understand😊
I updated the Codepen with comments. Let me know if more details are needed.
Thanku alvaro😊
My solution in clumsy Haskell:
Going functional in Perl:
There's probably a better way which requires only one iteration?
i want to contribute my idea with your code. i hope u enjoy with that. Maybe it's shoter
players.sort((a, b) => {return (a.points == b.points ? a.name > b.name : a.points < b.points) || -1;
}).map((e,i)=>({...e,position:(i+1)}))
Just a short one in Javascript
Edit: somehow I hadn't noticed the
positionbit 😳, so I've added that as a map call.Here it goes!
And the result:
Python
Shouldn't John's position in the example be 3?