Challenge description

You have a music library with many tracks recorded by many bands, each of which has a name, like Queen, Aerosmith, Sunny Day Real Estate, The Strokes . When an audio player displays your library alphabetically by band name, it usually skips the The part, as many band names start with The, making it easier to navigate through your media collection. In this challenge, given a list (array) of strings, you need to sort it that way (that is, omitting the The word at the beginning of the name). You can either write a method or a full working program.

Sample inputs / outputs

[Queen, Aerosmith, Sunny Day Real Estate, The Strokes] -> [Aerosmith, Queen, The Strokes, Sunny Day Real Estate]
[The Ramones, The Cure, The Pixies, The Roots, The Animals, Enrique Iglesias] -> [The Animals, The Cure, Enrique Iglesias, The Pixies, The Ramones, The Roots]
[The The, The They, Thermodynamics] -> [The The, Thermodynamics, The They]

Notes / Edge cases

  • Sorting lexicographically is case insensitive, so The Police, The police and the police are all equivalent,

  • Your algorithm should only omit the first the word, so bands named The The or The The Band are sorted normally by the second the,

  • A band named The (a three letter word) is sorted normally (no skipping),

  • Order of two bands having the same name, one of which starts with the (like The Police and Police) is undefined,

  • You can assume that if a band's name consists of more than one word, they are separated by a single space character. You don't need to handle leading or trailing whitespaces,

  • All input strings match [A-Za-z0-9 ]*, that is they will consist only of lower- and uppercase letters of English alphabet, digits and space characters,

  • Remember that this is a challenge, so make your code as short as possible!

  • \$\begingroup\$ Do numeral-only names come before or after alphabetical? \$\endgroup\$ Aug 2, 2016 at 19:24
  • \$\begingroup\$ Numeral-only strings come first \$\endgroup\$
    – shooqie
    Aug 2, 2016 at 19:42
  • 1
    \$\begingroup\$ What is the sort order of The and The The? ( Most answers would probably need to change if it is anything other than undefined ) \$\endgroup\$ Aug 3, 2016 at 0:15
  • \$\begingroup\$ how about Los Lobos? \$\endgroup\$
    – njzk2
    Aug 3, 2016 at 2:26
  • 5
    \$\begingroup\$ The The is a real band by the way. (along with The Who, The What, The Where, The When, The Why, and The How) \$\endgroup\$
    – DanTheMan
    Aug 3, 2016 at 2:33

24 Answers 24


Python, 56 62 64 bytes

lambda b:sorted(b,key=lambda x:(x,x[4:])[x.lower()[:4]=='the '])

Try it

Thanks to @Chris H for pointing out that lstrip() was not handling The The correctly, since the strip was blasting all matching characters and sorting it as a blank string, and @manatwork for finding the flaw in using replace(). The new version should work.

Old version:

lambda b:sorted(b,key=lambda x:x.lower().lstrip('the '))
  • 1
    \$\begingroup\$ I'm not convinced. Adding "The animals" to the last list gives ['The The', 'The', 'The Animals', 'Thermodynamics', 'The They']. The 2nd edge case suggest sit should be ['The Animals', 'The The', 'The', 'Thermodynamics', 'The They'] (or swap the 2nd and 3rd items). A little fiddling suggests the space inside strip('the ') is being ignored - try for x in ['The The', 'The They', 'Thermodynamics', 'The', 'The Animals']: print (x.lower().strip('the ')) \$\endgroup\$
    – Chris H
    Aug 3, 2016 at 8:54
  • \$\begingroup\$ That replace() is not much better: 'what the snake'.replace('the ','',1) results 'what snake'. \$\endgroup\$
    – manatwork
    Aug 3, 2016 at 11:00

V, 32 28 bytes

ç^The /dwA_

Try it online!

Note to self: Make an abbreviation for :sort so that I don't need 6 whole bytes for a single command!


ç^The /     "On every line starting with 'The ',
       dw   "Delete a word
         A_ "And (A)ppend an underscore '_'

:sort       "Sort all lines alphabetically

ç_/         "On every line containing an underscore,
   $x       "Delete the last character
     IThe   "And prepened 'The '
  • \$\begingroup\$ Not familiar with V, but it seems this one works fine without the asterisks. Is this coincidence with the input, or actually unneeded? \$\endgroup\$
    – kirkpatt
    Aug 2, 2016 at 21:46
  • 1
    \$\begingroup\$ @kirkpatt Good idea! That almost works, but not quite. For example, with this input it incorrectly puts "Radiohead" after "The Ramones" and "The Roots". However, that gives me an idea... \$\endgroup\$
    – DJMcMayhem
    Aug 2, 2016 at 22:04
  • \$\begingroup\$ What happens if the is in all lowercase, like the pAper chAse? \$\endgroup\$ Aug 3, 2016 at 12:44

Retina, 34 bytes

The trailing linefeed is significant.



I/O is one band per line.

Try it online!



Duplicate each line, using ; as a separator.


Turn everything in front of a ; to lower case.


Remove any thes that appear at the beginning of a line.


Sort the lines.


Remove the beginnings of the lines which we used for sorting.

  • \$\begingroup\$ Couldn't you pack the first 3 Steps into a single step? Like in PCRE: s/(?i:the )?(.*)/\L$1\E;$0/ \$\endgroup\$
    – Falco
    Aug 3, 2016 at 11:15
  • \$\begingroup\$ @Falco .NET doesn't support case changes in substitution strings and I haven't yet added them to Retina's custom replacer either. \$\endgroup\$ Aug 3, 2016 at 11:23

Pyke, 16 bytes

.#l1D"the ".^4*>

Try it here!

.#                - sort_by(V, input)
  l1              -  i = i.lower()
      "the ".^    -   i.startswith("the ")
              I   -  if ^:
               4> -   i[4:]

Perl, 52 bytes

-13 byte thanks to @manatwork
-1 byte thanks to @msh210

sub f{lc pop=~s/^the //ri}print sort{f($a)cmp f$b}<>

One band per line as input, and so is the output.

The implementation is quite straight forward : the program prints the list of bands, sorted with the help of a custom function (f) which returns the lower case band name without the eventual leading the .

  • \$\begingroup\$ Is shorter with substitution instead of matching: sub f{lc$_[0]=~s/^the //ir}. \$\endgroup\$
    – manatwork
    Aug 3, 2016 at 9:08
  • \$\begingroup\$ 1 byte shorter indeed, thanks. \$\endgroup\$
    – Dada
    Aug 3, 2016 at 9:18
  • \$\begingroup\$ Actually I counted either 2 or 3 bytes shorter: no need for both the parenthesis around lc's parameter and the i flag in substitution. Or have you met a test case where that not works? \$\endgroup\$
    – manatwork
    Aug 3, 2016 at 10:16
  • \$\begingroup\$ Thinking again, the amount of command line options could also be reduced if you take each band name on separate line: perl -e 'sub f{lc$_[0]=~s/^the //ri}print sort{f($a)cmp f$b}<>' <<< $'Queen\nAerosmith\nSunny Day Real Estate\nThe Strokes'. \$\endgroup\$
    – manatwork
    Aug 3, 2016 at 10:42
  • 1
    \$\begingroup\$ Save three bytes: lc pop instead of lc$_[0], and say instead of print. (The latter requires -M5.01, which is free.) Tested in Strawberry 5.20.2 with only the first test case from the question. \$\endgroup\$
    – msh210
    Aug 3, 2016 at 15:59

Python, 66 72 69 bytes

lambda x:sorted(x,key=lambda a:a[4*(a.lower()[:4]=='the '):].lower())

Uses Python's sorted method with the key keyword argument to sort by the name minus "The". This is a lambda; to call it, give it a name by putting f= in front.

Now with extra case insensitivity!

  • 2
    \$\begingroup\$ It doesn't meet the case insensitivity requirement, though... A band name can start with the , in which case this method won't work properly. \$\endgroup\$
    – shooqie
    Aug 2, 2016 at 19:21
  • \$\begingroup\$ @shooqie Oh, I didn't see that requirement. I'll fix it. \$\endgroup\$
    – Copper
    Aug 2, 2016 at 19:22

Ruby, 42 bytes

->a{a.sort_by{|s|s.upcase.sub /^THE /,''}}

Try it online!


Perl 6, 26 bytes

*.sort({fc S:i/^'the '//})


# 「*」 is the input to this Whatever lambda

  # sort based on the return value of this Block lambda
    fc # foldcase the following

    # string replace but not in-place
        # at the start of the string

        # match 「the 」
        'the '

      # replace with nothing


use v6.c;
use Test;

my @tests = (
  « Queen Aerosmith 'Sunny Day Real Estate' 'The Strokes' »
    => « Aerosmith Queen 'The Strokes' 'Sunny Day Real Estate' »,
  « 'The Ramones' 'The Cure' 'The Pixies' 'The Roots' 'The Animals' 'Enrique Iglesias' »
    => « 'The Animals' 'The Cure' 'Enrique Iglesias' 'The Pixies' 'The Ramones' 'The Roots' »,
  « 'The The' 'The They' Thermodynamics »
    => « 'The The' Thermodynamics 'The They' »,

# give it a lexical name for clarity
my &band-sort = *.sort({fc S:i/^'the '//});

plan +@tests;

for @tests -> ( :key(@input), :value(@expected) ) {
  is-deeply band-sort(@input), @expected, @expected.perl;
ok 1 - ("Aerosmith", "Queen", "The Strokes", "Sunny Day Real Estate")
ok 2 - ("The Animals", "The Cure", "Enrique Iglesias", "The Pixies", "The Ramones", "The Roots")
ok 3 - ("The The", "Thermodynamics", "The They")

PowerShell v2+, 33 32 29 bytes

$args|sort{$_-replace'^the '}

Saved 3 bytes thanks to @MathiasRJessen

Input is via command-line arguments. Sorts the original names based on the results of the script block {...} that performs a regex -replace to strip out the leading (case-insensitive) "the ".


PS C:\Tools\Scripts\golfing> .\sort-band-names.ps1 'the Ramones' 'The cure' 'The Pixies' 'The Roots' 'the Animals' 'Enrique Iglesias'
the Animals
The cure
Enrique Iglesias
The Pixies
the Ramones
The Roots

PS C:\Tools\Scripts\golfing> .\sort-band-names.ps1 'The The' 'The They' 'Thermodynamics'
The The
The They

PS C:\Tools\Scripts\golfing> .\sort-band-names.ps1 'THE STOOGES' 'The Strokes' 'The The' 'the they' 'the band' 'STP'
the band
The Strokes
The The
the they
  • \$\begingroup\$ -replace is case-insensitive by default, '^the ' will suffice for the pattern \$\endgroup\$ Aug 3, 2016 at 10:17
  • \$\begingroup\$ @MathiasR.Jessen Yes, thanks for the reminder. \$\endgroup\$ Aug 3, 2016 at 12:32
  • \$\begingroup\$ @ValueInk See Mathias' comment about case insensitivity and the final example I added. \$\endgroup\$ Aug 3, 2016 at 12:33

JavaScript/ECMAScript 6 93 70 bytes

70 Thanks to Neil and Downgoat for advice

B=>B.sort((a,b)=>R(a).localeCompare(R(b)),R=s=>s.replace(/^the /i,''))

Readable Version for the 70-byte variant

let sortBandNames = (bandNames) => {
    let stripThe = (name) => name.replace(/^the /i, '');
    let compareFunc = (a, b) => stripThe(a).localeCompare(stripThe(b));
    return bandNames.sort(compareFunc)


f=B=>{R=s=>s.toLowerCase().replace(/the /,'');return B.sort((a,b)=>R(a).localeCompare(R(b)))}

Readable Version for the 93-byte variant

let sortBandNames = (bandNames) => {
    let stripThe = (name) => name.toLowerCase().replace(/the /, '');
    let compareFunc = (a, b) => stripThe(a).localeCompare(stripThe(b));
    return bandNames.sort(compareFunc)
  • \$\begingroup\$ Shouldn't that regexp have a ^ in it? Also, localeCompare is case insensitive on my system, so I didn't need the toLowerCase, just an /i flag on the regexp. Finally you can golf this as follows: B=>B.sort((a,b)=>...,R=s=>...) - sort ignores the extra parameter that sets R. \$\endgroup\$
    – Neil
    Aug 2, 2016 at 20:24
  • \$\begingroup\$ Where in the regex would ^ go? That would be a negation and the the expression is supposed to match and erase "the ". I'll try using locale compare without the lower-case conversion. \$\endgroup\$
    – Pandacoder
    Aug 2, 2016 at 22:39
  • \$\begingroup\$ @Pandacoder the ^ shuold go at the beginning of the regex \$\endgroup\$
    – Downgoat
    Aug 2, 2016 at 23:16
  • \$\begingroup\$ @Downgoat From testing all of the given cases, and a few cases I came up with specifically intending to break the RegEx, with or without the ^ I get no change in behavior, only an extra character that doesn't accomplish anything. \$\endgroup\$
    – Pandacoder
    Aug 2, 2016 at 23:52
  • \$\begingroup\$ @Pandacoder that doesn't make it valid. the ^ is an anchor which requires the "the" to be at the beginning per the spec \$\endgroup\$
    – Downgoat
    Aug 2, 2016 at 23:58

Java 8, 178 bytes

void q(String[]s){java.util.Arrays.sort(s,(a,b)->(a.toLowerCase().startsWith("the ")?a.substring(4):a).compareToIgnoreCase(b.toLowerCase().startsWith("the ")?b.substring(4):b));}

Ungolfed version:

void sort(String[] bands) {
    java.util.Arrays.sort(bands, (a, b) -> 
        (a.toLowerCase().startsWith("the ") ? a.substring(4) : a).compareToIgnoreCase(
            b.toLowerCase().startsWith("the ") ? b.substring(4) : b

Call as such:

public static void main(String[] args) {
    String[] bands = {"The Strokes", "Queen", "AC/DC", "The Band", "Cage the Elephant", "cage the elephant"};
    sort(bands); // or q(bands) in the golfed version
  • \$\begingroup\$ I know you've answered this almost a year ago, but you can golf a few things. Since you state you use Java 8, you can change void q(String[]s){...} to s->{...}. And you can change both (x.toLowerCase().startsWith("the ")?x.substring(4):x) with x.replaceFirst("(?i)the ",""). So the total becomes: s->{java.util.Arrays.sort(s,(a,b)->a.replaceFirst("(?i)the ","").compareToIgnoreCase(b.replaceFirst("(?i)the ","")));} - 118 bytes \$\endgroup\$ Sep 18, 2017 at 13:56
  • \$\begingroup\$ Neat trick with the replaceFirst. When I answered this I had been told a few times on other answers that s->{ ... } wasn't allowed and I had to have a full method signature with types and whatnot. I don't know if that's changed since then. \$\endgroup\$
    – Justin
    Sep 18, 2017 at 16:06
  • \$\begingroup\$ Not sure about back then, but these days it's allowed and used by close to everyone golfing in Java or C# .NET. \$\endgroup\$ Sep 18, 2017 at 21:14

Bash + coreutils, 44 bytes

sed '/^the /I!s,^,@ ,'|sort -dk2|sed s,@\ ,,

Explanation: the input and output format is one band per line

sed '/^the /I!s,^,@ ,'   # prepend '@ ' to each line not starting with 'the ', case
                         #insensitive. This adds a temporary field needed by sort.
sort -dk2                # sort in ascending dictionary order by 2nd field onward
sed s,@\ ,,              # remove the temporary field

Test run (using a here-document with EOF as the end marker):

./sort_bands.sh << EOF
> Queen
> Aerosmith
> Sunny Day Real Estate
> The Strokes


The Strokes
Sunny Day Real Estate

Vim, 18 bytes

Well now that I realized this is possible, I'm kinda embarrassed by my 26 byte V answer, especially since V is supposed to be shorter than vim. But this is pretty much a builtin.

:sor i/\(The \)*/<CR>

Explanation (straight from vim help):

                            *:sor* *:sort*
:[range]sor[t][!] [b][f][i][n][o][r][u][x] [/{pattern}/]
            Sort lines in [range].  When no range is given all
            lines are sorted.

            With [i] case is ignored.

            When /{pattern}/ is specified and there is no [r] flag
            the text matched with {pattern} is skipped, so that
            you sort on what comes after the match.
            Instead of the slash any non-letter can be used.

C, 216 212 135 + 5 (qsort) = 221 217 140 bytes

M(void*a,void*b){char*A,*B;A=*(char**)a;B=*(char**)b;A=strcasestr(A,"The ")?A+4:A;B=strcasestr(B,"The ")?B+4:B;return strcasecmp(A,B);}

Well, I finally got around to finishing this in C. Golfing tips are very much appreciated.

In this submission, M is the comparison function to be supplied to qsort. Therefore, to invoke this, you must use qsort in the format qsort(argv++,argc--,8,M) where argv contains the command-line arguments and argc is the number of arguments provided.

Try It Online!


Nim, 96 bytes

import algorithm,strutils,future
x=>x.sortedByIt toLower it[4*int(it.toLower[0..3]=="the ")..^0]

Those imports take up so many bytes :|

A translation of my Python answer.

This is an anonymous procedure; to use it, it must be passed into a testing procedure. Here's a full program you can use for testing:

import algorithm,strutils,future
proc test(x: seq[string] -> seq[string]) =
 echo x(@["The The", "The They", "Thermodynamics"]) # Substitute your input here
test(x=>x.sortedByIt toLower it[4*int(it.toLower[0..3]=="the ")..^0])

Haskell, 84 bytes

import Data.List
p(t:'h':'e':' ':s)|elem t"Tt"=s
p s=s
sortBy(\a b->p a`compare`p b)

Call with

sortBy(\a b->p a`compare`p b)["The The", "The They", "Thermodynamics"]


let s = sortBy(\a b->p a`compare`p b)
and[s["Queen", "Aerosmith", "Sunny Day Real Estate", "The Strokes"]==["Aerosmith", "Queen", "The Strokes", "Sunny Day Real Estate"],s["The Ramones", "The Cure", "The Pixies", "The Roots", "The Animals", "Enrique Iglesias"]==["The Animals", "The Cure", "Enrique Iglesias", "The Pixies", "The Ramones", "The Roots"],s["The The", "The They", "Thermodynamics"]==["The The", "Thermodynamics", "The They"]]

MATL, 16 bytes

tk'^the '[]YX2$S

Input format is (each line corresponds to a test case)

{'Queen', 'Aerosmith', 'Sunny Day Real Estate', 'The Strokes'} 
{'The Ramones', 'The Cure', 'The Pixies', 'The Roots', 'The Animals', 'Enrique Iglesias'}
{'The The', 'The They', 'Thermodynamics'}

Try it online!


t        % Implicitly input cell array of strings. Push another copy
k        % Convert to lowercase
'^the '  % String to be used as regex pattern: matches initial 'the '
[]       % Empty array
YX       % Regex replacement: replace initial 'the ' in each string by empty array
2$S      % Sort input according to the modified cell array. Implicitly display

C#, 139 Bytes

using System.Linq;System.Collections.IEnumerable S(string[] l)=> l.OrderBy(b=>(b.ToLower().StartsWith("the ")?b.Substring(4):b).ToLower());

Try online!

Without counting the usings the answer would be 102 bytes.

  • \$\begingroup\$ I believe you can ignore the final ToLower() due to the case-insensitive requirement \$\endgroup\$ Aug 4, 2016 at 15:05
  • \$\begingroup\$ Also you can make it an anonymous function which should save some bytes: \$\endgroup\$ Aug 4, 2016 at 15:07
  • \$\begingroup\$ l=>l.OrderBy(b=>(b.ToLower().StartsWith("the ")?b.Substring(4):b)); For 67 bytes and then you need to add on the using System.Linq; too \$\endgroup\$ Aug 4, 2016 at 15:12
  • \$\begingroup\$ @TheLethalCoder: I need the second ToLower because of the case-insensitive requirement. Otherwise the order would be case-sensitive. \$\endgroup\$
    – raznagul
    Aug 4, 2016 at 15:38
  • \$\begingroup\$ Okay the point about converting it to an anonymous function still stands though \$\endgroup\$ Aug 4, 2016 at 15:42

BASH, 64 Bytes

sed 's/^the / /;s/^The /    /'|sort -fb|sed 's/^ /the /;s/^ /The /'

Input: stdin, one band per line. Output: stdout

Note: The second replacements (s/^The/ / and s/^ /The /) use the tab character, so they don't always copy/paste correctly.


Groovy, 34 bytes

{it.sort{it.toLowerCase()-'the '}}

41% my answer is .toLowerCase(), kill me now.


When running...

({it.sort{it.toLowerCase()-'the '}})(['The ramones','The Cure','The Pixies','The Roots','The Animals','Enrique Iglesias'])

The result is...

[The Animals, The Cure, Enrique Iglesias, The Pixies, The ramones, The Roots]

With no debug or error output.


q/kdb+, 36 33 bytes


{x(<)@[x;(&)x like"[Tt]he *";4_]}


q){x(<)@[x;(&)x like"[Tt]he *";4_]}("Queen";"Aerosmith";"Sunny Day Real Estate";"The Strokes";"the Eagles")
"the Eagles"
"The Strokes"
"Sunny Day Real Estate"


Strip out any "[Tt]he " from each input string, sort this list, then sort the original list based on the indexing of the sorted list.

{x iasc @[x;where x like "[Tt]he *";4_]} / ungolfed solution
{                                      } / lambda function
        @[x;                       ;  ]  / apply function to x at indices
                                    4_   / 4 drop, remove first 4 items
            where x like "[Tt]he *"      / where the input matches 'The ...' or 'the ...'
   iasc                                  / returns sorted indices
 x                                       / index into original list at these indices

Japt, 11 10 bytes

ñ_v r`^e 

Try it


05AB1E, 27 bytes


Try it online!


vyð¡RD¤…TheQsgα£Rðý})‚øí{ø¤   Argument l
v                 }           For each y in l, do:
 yð¡                            Split y on space
    RD                          Reverse and duplicate
      ¤…TheQ                    Last element equals "The" (true = 1, false = 0)
            sgα                 Absolute difference with length of array
               £                Get elements from index 0 to calculated difference
                R               Reverse
                 ðý             Join on space
                    )‚øí      Pair each element with original
                        {ø¤   Sort and get the original band name

Java 176 158 bytes

public String[]sort(String[]names){
  for(int i=-1;++i<names.length;)
    if(names[i].startsWith("(The |the )"))
  return Arrays.sort(names,String.CASE_INSENSITIVE_ORDER);

Main Function

public static void main(String[]args){
  Scanner s = new Scanner(System.in);
  List<String> list= new ArrayList<>();
  while(!(String h = s.nextLine).equalsIgnoreCase("~")){

); }

Golfed sort function:

String[]s(String[]n){for(int i=-1;++i<n.length;)if(n[i].startsWith("(The |the )"))n[i]=n[i].substring(4);return Arrays.sort(n,String.CASE_INSENSITIVE_ORDER);}

Thanks to @raznagul for saving 18 bytes

  • \$\begingroup\$ Doesn't work if a name starts with the . The sort should be case insensitive. \$\endgroup\$
    – shooqie
    Aug 2, 2016 at 19:59
  • \$\begingroup\$ This won't work at all... Strings are immutable. You want to do public String[]sort(String[]names){ for(int i=-1;++i<names.length;) names[i]=names[i].replaceFirst("(the|The)", ""); return Arrays.sort(names,String.CASE_INSENSITIVE_ORDER); } Since the and The should work, and strings a immutable \$\endgroup\$ Aug 2, 2016 at 20:17
  • \$\begingroup\$ Fixed that, but find me one band that starts with a small "the " \$\endgroup\$ Aug 3, 2016 at 8:39
  • 2
    \$\begingroup\$ Arrays.sort returns type void \$\endgroup\$
    – user902383
    Aug 3, 2016 at 13:52
  • 1
    \$\begingroup\$ @RomanGräf the pAper chAse \$\endgroup\$ Aug 4, 2016 at 14:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.