Classificar nomes de bandas


22

Descrição do Desafio

Você tem uma biblioteca de música com muitas faixas gravadas por muitas bandas, cada um dos quais tem um nome, como Queen, Aerosmith, Sunny Day Real Estate, The Strokes. Quando um reprodutor de áudio exibe sua biblioteca em ordem alfabética pelo nome da banda, geralmente ignora a Theparte, como muitos nomes de banda iniciam The, facilitando a navegação pela coleção de mídia. Nesse desafio, dada uma lista (matriz) de cadeias, você precisa classificá-la dessa maneira (ou seja, omitir a Thepalavra no início do nome). Você pode escrever um método ou um programa de trabalho completo.

Amostras de entradas / saídas

[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]

Notas / casos de borda

  • Classificar lexicograficamente não faz distinção entre maiúsculas e minúsculas, portanto The Police, The policee the policesão todos equivalentes,

  • Seu algoritmo deve omitir apenas a primeira thepalavra, para que as bandas nomeadas The Theou The The Bandsejam classificadas normalmente pela segunda the,

  • Uma banda chamada The(uma palavra de três letras) é classificada normalmente (sem pular),

  • A ordem de duas bandas com o mesmo nome, uma das quais começa com the(como The Policee Police) é indefinida,

  • Você pode assumir que, se o nome de uma banda consistir em mais de uma palavra, eles serão separados por um único caractere de espaço. Você não precisa lidar com espaços em branco iniciais ou finais,

  • Todas as cadeias de entrada correspondem [A-Za-z0-9 ]*, ou seja, elas consistem apenas em letras maiúsculas e minúsculas do alfabeto inglês, dígitos e caracteres de espaço,

  • Lembre-se de que este é um desafio do , portanto, faça o seu código o mais curto possível!


Os nomes apenas de números vêm antes ou depois do alfabeto?
AdmBorkBork 02/08

Numeral somente cordas vêm em primeiro lugar
shooqie

1
Qual é a ordem de classificação de Thee The The? (A maioria das respostas provavelmente precisa mudar se é outra coisa senão indefinido)
Brad Gilbert b2gills

e quanto a Los Lobos?
Njzk2 03/08/19

3
The The é uma banda real, a propósito. (juntamente com The Who, O Quê, Onde, quando, por quê, eo como)
DanTheMan

Respostas:


7

Python, 56 62 64 bytes

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

Tente

Agradecemos a @Chris H por apontar que lstrip()não estava lidando The Thecorretamente, pois a faixa estava detonando todos os caracteres correspondentes e classificando-os como uma sequência em branco, e a @manatwork por encontrar a falha no uso replace(). A nova versão deve funcionar.

Versão antiga:

lambda b:sorted(b,key=lambda x:x.lower().lstrip('the '))

1
Não estou convencido. Adicionar "Os animais" à última lista fornece ['The The', 'The', 'The Animals', 'Thermodynamics', 'The They']. O caso da 2ª aresta sugere que o sit deve ser ['Os Animais', 'O', 'O', 'Termodinâmica', 'O Eles'] (ou troque os itens 2 e 3). Um pouco de mexer sugere o interior do espaço strip('the ')está a ser ignorado - tentativafor x in ['The The', 'The They', 'Thermodynamics', 'The', 'The Animals']: print (x.lower().strip('the '))
Chris H

Isso replace()não é muito melhor: 'what the snake'.replace('the ','',1)resultados 'what snake'.
manatwork

5

V , 32 28 bytes

ç^The /dwA_
:sort
ç_/$xIThe 

Experimente online!

Nota para si mesmo: faça uma abreviação de :sortpara que eu não precise de 6 bytes inteiros para um único comando!

Explicação:

ç^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 '

Não estou familiarizado com V, mas parece que este funciona bem sem os asteriscos. Essa coincidência com a entrada é realmente desnecessária?
precisa saber é o seguinte

1
@kirkpatt Good idea! Isso quase funciona, mas não completamente. Por exemplo, com esta entrada, ele coloca incorretamente "Radiohead" depois de "The Ramones" e "The Roots". No entanto, isso me dá uma idéia ...
DJMcMayhem

O que acontece se theestiver em minúsculas, como the pAper chAse?
AdmBorkBork

4

Retina , 34 bytes

O avanço de linha à direita é significativo.

%`^
$';
T`L`l`.+;
m`^the 

O`
.+;

E / S é uma banda por linha.

Experimente online!

Explicação

%`^
$';

Duplique cada linha, usando ;como separador.

T`L`l`.+;

Vire tudo na frente de um ;para minúsculo.

m`^the 

Remova todos os thes que aparecerem no início de uma linha.

O`

Classifique as linhas.

.+;

Remova o início das linhas que usamos para classificação.


Você não conseguiu agrupar os três primeiros passos em um único passo? Como em PCRE: s / (?i:the )?(.*)/ \L$1\E;$0/
Falco

O @Falco .NET não suporta alterações de caso em cadeias de substituição e ainda não as adicionei ao substituto personalizado da Retina.
Martin Ender

4

Pyke, 16 bytes

.#l1D"the ".^4*>

Experimente aqui!

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

3

Perl, 52 bytes

-13 byte graças a @manatwork
-1 byte graças a @ msh210

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

Uma banda por linha como entrada e a saída também.

A implementação é bastante direta: o programa imprime a lista de bandas, classificadas com a ajuda de uma função personalizada ( f) que retorna o nome da banda em minúsculas sem a eventual liderança the.


É mais curto com substituição em vez de correspondência: sub f{lc$_[0]=~s/^the //ir}.
Manatwork 03/08/19

1 byte mais curto, obrigado.
Dada

Na verdade, contei 2 ou 3 bytes mais curtos: não é necessário o lcparâmetro entre parênteses e o isinalizador em substituição. Ou você conheceu um caso de teste em que isso não funciona?
manatwork

Pensando novamente, a quantidade de opções de linha de comando também poderia ser reduzido se você tomar o nome de cada banda em linha separada: perl -e 'sub f{lc$_[0]=~s/^the //ri}print sort{f($a)cmp f$b}<>' <<< $'Queen\nAerosmith\nSunny Day Real Estate\nThe Strokes'.
manatwork

1
Salve três bytes: em lc popvez de lc$_[0]e em sayvez de print. (O último requer -M5.01, que é gratuito.) Testado no Strawberry 5.20.2 com apenas o primeiro caso de teste da pergunta.
Msh210

2

Python, 66 72 69 bytes

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

Usa o sortedmétodo Python com o keyargumento keyword para classificar pelo nome menos "The". Isso é uma lambda; para chamá-lo, dê um nome colocando-o f=na frente.

Agora com insensibilidade extra à caixa!


2
Porém, ele não atende ao requisito de insensibilidade de maiúsculas e minúsculas ... Um nome de banda pode começar the ; nesse caso, esse método não funcionará corretamente.
Shooqie 02/08/16

@shooqie Oh, eu não vi esse requisito. Eu resolvo isso.
Copper


2

Perl 6 , 26 bytes

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

Explicação:

# 「*」 is the input to this Whatever lambda
*.sort(

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

    # string replace but not in-place
    S
      :ignorecase
      /
        # at the start of the string
        ^

        # match 「the 」
        'the '

      # replace with nothing
      //
  }
)

Teste:

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;
}
1..3
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")

2

PowerShell v2 +, 33 32 29 bytes

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

Guardado 3 bytes graças a @MathiasRJessen

A entrada é via argumentos da linha de comando. Classifica os nomes originais com base nos resultados do bloco de scripts {...}que executa uma regex -replacepara remover os principais (sem distinção entre maiúsculas e minúsculas) "the ".

Exemplos

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
Thermodynamics
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 STOOGES
STP
The Strokes
The The
the they

-replaceé case-insensitive por padrão, '^the 'será suficiente para o padrão
Mathias R. Jessen

@ MathiasR.Jessen Sim, obrigado pelo lembrete.
AdmBorkBork

@ValueInk Veja o comentário de Mathias sobre insensibilidade ao caso e o exemplo final que adicionei.
AdmBorkBork

2

JavaScript / ECMAScript 6 93 70 bytes

70 Agradecimentos a Neil e Downgoat pelos conselhos

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

Versão legível para a variante de 70 bytes

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

93

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

Versão legível para a variante de 93 bytes

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

Esse regexp não deveria ter um ^? Além disso, o localeCompare não faz distinção entre maiúsculas e minúsculas no meu sistema, por isso não precisava do sinal toLowerCase, apenas uma /isinalização no regexp. Finalmente, você pode jogar isto da seguinte maneira: B=>B.sort((a,b)=>...,R=s=>...)- sortignora o parâmetro extra que define R.
Neil

Para onde no regex ^ iria? Isso seria uma negação e a expressão deve corresponder e apagar "o". Vou tentar usar a comparação de localidade sem a conversão em minúsculas.
Pandacoder

@Pandacoder o ^movimento shuold no início da regex
Downgoat

@Downgoat Ao testar todos os casos fornecidos, e em alguns casos, tive a intenção específica de quebrar o RegEx, com ou sem o ^ Não recebo nenhuma alteração no comportamento, apenas um caractere extra que não realiza nada.
Pandacoder

@ Pandacoder que não o torna válido. the ^ é uma âncora que requer que o "the" esteja no começo de acordo com as especificações
Downgoat

1

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));}

Versão não destruída:

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
        )
    );
}

Ligue como tal:

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
    System.out.println(java.util.Arrays.toString(bands));
}

Sei que você respondeu isso há quase um ano, mas você pode jogar golfe algumas coisas. Como você declara usar o Java 8, pode mudar void q(String[]s){...}para s->{...}. E você pode mudar os dois (x.toLowerCase().startsWith("the ")?x.substring(4):x)com x.replaceFirst("(?i)the ",""). Assim, o total se torna: s->{java.util.Arrays.sort(s,(a,b)->a.replaceFirst("(?i)the ","").compareToIgnoreCase(b.replaceFirst("(?i)the ","")));}- 118 bytes
Kevin Cruijssen 18/17

Truque elegante com o replaceFirst. Quando respondi a isso, algumas vezes me disseram outras respostas que s->{ ... }não eram permitidas e eu tinha que ter uma assinatura de método completa com tipos e outros enfeites. Não sei se isso mudou desde então.
Justin

Não tenho certeza sobre a época, mas hoje em dia é permitido e usado por quase todos que praticam golfe em Java ou C # .NET.
Kevin Cruijssen

0

Nim , 96 bytes

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

Esses importocupam tantos bytes:|

Uma tradução da minha resposta Python .

Este é um procedimento anônimo; Para usá-lo, ele deve ser passado para um procedimento de teste. Aqui está um programa completo que você pode usar para testar:

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])

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)

Ligue com

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

Caso de teste:

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"]]

0

MATL , 16 bytes

tk'^the '[]YX2$S

O formato de entrada é (cada linha corresponde a um caso de teste)

{'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'}

Experimente online!

Explicação

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

0

C #, 139 bytes

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

Experimente online!

Sem contar os usos, a resposta seria 102 bytes.


Eu acredito que você pode ignorar a final ToLower()devido à exigência de maiúsculas e minúsculas
TheLethalCoder

Além disso, você pode torná-lo uma função anônima que deve salvar alguns bytes:
TheLethalCoder

l=>l.OrderBy(b=>(b.ToLower().StartsWith("the ")?b.Substring(4):b));Para 67 bytes e, em seguida, você precisa adicionar na using System.Linq;também
TheLethalCoder

@TheLethalCoder: preciso do segundo ToLowerpor causa do requisito que não diferencia maiúsculas de minúsculas. Caso contrário, o pedido faria distinção entre maiúsculas e minúsculas.
raznagul

Ok o ponto sobre convertê-lo para uma função anônima continua de pé embora
TheLethalCoder

0

BASH, 64 bytes

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

Entrada: stdin, uma banda por linha. Saída: stdout

Nota: As segundas substituições (s / ^ The / / s / ^ / The /) usam o caractere de tabulação, portanto nem sempre copiam / colam corretamente.


0

Bash + coreutils, 44 bytes

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

Explicação: o formato de entrada e saída é uma banda por linha

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

Execução de teste (usando um documento aqui com EOF como marcador final):

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

Saída:

Aerosmith
Queen
The Strokes
Sunny Day Real Estate

0

Vim, 18 bytes

Bem, agora que percebi que isso é possível, estou meio envergonhado com a minha resposta V de 26 bytes, especialmente porque o V deve ser mais curto que o vim. Mas isso é praticamente um builtin.

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

Explicação (diretamente da ajuda do vim):

                            *: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.

0

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);}

Bem, finalmente consegui terminar isso C. Dicas de golfe são muito apreciadas.

Nesta submissão, Mé a função de comparação a ser fornecida qsort. Portanto, para invocar isso, você deve usar qsortno formato em qsort(argv++,argc--,8,M)que argvcontém os argumentos da linha de comandos eargc é o número de argumentos fornecidos.

Experimente Online!


0

05AB1E , 27 bytes (não concorrente)

vyð¡RD¤…TheQsgα£Rðý})‚øí{ø¤

Experimente online!

Explicação

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

0

Groovy, 34 bytes

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

41% a minha resposta é .toLowerCase(), me mate agora.


Saída

Ao executar ...

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

O resultado é...

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

Sem saída de depuração ou erro.


0

q / kdb +, 36 33 bytes

Solução:

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

Exemplo:

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

Explicação:

Retire qualquer "[Tt] ele" de cada sequência de entrada, classifique esta lista e, em seguida, classifique a lista original com base na indexação da lista classificada.

{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


-2

Java 176 158 bytes

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

Função principal

public static void main(String[]args){
  Scanner s = new Scanner(System.in);
  List<String> list= new ArrayList<>();
  while(!(String h = s.nextLine).equalsIgnoreCase("~")){
    list.add(h);
  }
System.out.println(sort(list.toArray(newString[0]))

); }

Função de classificação Golfed:

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);}

Obrigado a @raznagul por salvar 18 bytes


Não funciona se um nome começa com the . A classificação não diferencia maiúsculas de minúsculas.
Shooqie 2/08

Isso não vai funcionar ... As strings são imutáveis. Você quer fazer 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); }Como o e A deve funcionar, e cordas de um imutável
socrático Phoenix

Corrigido isso, mas encontre uma banda que comece com um pequeno "the"
Roman Gräf

2
Arrays.sortRetorna o tipo void
user902383

1
@ RomanGräfthe pAper chAse
AdmBorkBork
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.