Deinterleave log lines [duplicate]
Hai ereditato un server che esegue diverse app che vengono tutte visualizzate nello stesso registro.
Il tuo compito è deinterleave le righe del file di log in base alla fonte. Fortunatamente, ogni riga inizia con un tag che indica da quale app proviene.
Registri
Ogni riga avrà un aspetto simile a questo:
[app_name] Something horrible happened!
- I tag delle app sono sempre tra parentesi quadre e conterranno solo caratteri alfanumerici e trattini bassi.
- Tutte le righe avranno un tag app all'inizio. Non ci saranno spazi bianchi precedenti o altri caratteri.
- Ci sarà sempre almeno uno spazio dopo il tag dell'app
- I tag delle app non sono vuoti
- Potrebbero esserci altre parentesi quadre più avanti su una determinata riga.
- Potrebbe esserci o meno un messaggio dopo il tag
- Il registro potrebbe essere vuoto
- Non c'è limite al numero di tag di app univoci presenti nel file.
Esempio
Un intero registro potrebbe essere simile a questo:
[weather] Current temp: 83F
[barkeep] Fish enters bar
[barkeep] Fish orders beer
[stockmarket] PI +3.14
[barkeep] Fish leaves bar
[weather] 40% chance of rain detected
Che dovrebbe produrre tre diversi registri:
[weather] Current temp: 83F
[weather] 40% chance of rain detected
[barkeep] Fish enters bar
[barkeep] Fish orders beer
[barkeep] Fish leaves bar
[stockmarket] PI +3.14
Non ti vengono forniti i nomi dei tag dell'app in anticipo. È necessario determinarli solo analizzando il file di registro.
Regole e punteggio
- Questo è il golf in codice , quindi il codice più breve vince.
- Si applicano regole e scappatoie standard
- Utilizza qualsiasi formato IO conveniente, a condizione che ogni riga di input sia rappresentata come una stringa, non come un tag pre-analizzato + un messaggio. Elenco non esaustivo degli output consentiti:
- Diversi file denominati dopo ogni tag
- Diversi elenchi di stringhe
- Un elenco concatenato di stringhe contenente righe raggruppate per tag con o senza separatore (il separatore non deve iniziare con un tag)
- Come sopra, ma per stdout o un file.
- L'ordine in cui vengono emessi i registri separati è irrilevante, tuttavia le righe di registro all'interno di ogni gruppo devono mantenere l'ordine in cui sono state trovate nel file originale
Risposte
Bash , 4 11 byte
Aggiunti 7 byte per correggere un bug gentilmente segnalato da Shaggy .
sort -sk1,1
Provalo online!
Esegue un ordinamento stabile (l' s
argomento della riga di comando) in base al primo campo ( k1,1
) separato da spazi.
R , 50 46 byte
function(r)split(r,substr(r,1,regexpr("]",r)))
Provalo online!
Emette come a list
con ogni elemento name
d con [tag]
. Ogni elemento della lista mantiene l'ordine all'interno del proprio tag. Restituisce un elenco con nome named list()
vuoto per input vuoto.
-2 byte ciascuno grazie a Robin Ryder e Dominic van Essen!
Pyth , 3 byte
ohc
Provalo online!
Il formato di input è un elenco di stringhe:
["[weather] Current temp: 83F","[barkeep] Fish enters bar","[barkeep] Fish orders beer","[stockmarket] PI +3.14","[barkeep] Fish leaves bar","[weather] 40% chance of rain detected"]
Come funziona il codice:
o
: Ordinato dah
: Il primo elemento dic
: Ogni stringa suddivisa in spazi
Python , 44 byte
lambda a:sorted(a,key=lambda l:l.split()[0])
Provalo online!
Loose I / O ci consente di prendere e generare un elenco di righe. Dal momento che non dobbiamo separare i gruppi, il problema si riduce all'esecuzione di un ordinamento stabile delle righe sul prefisso di ciascuna riga fino al primo spazio, split()
verranno divise anche in altri caratteri di spazio bianco ma nessuna può essere presente in la parte del tag dell'applicazione.
APL (Dyalog Extended) , 10 byte ( SBCS )
Funzione di prefisso tacito anonimo. Accetta un elenco di elenchi di caratteri come argomento. Restituisce una matrice di elenchi di caratteri, con un registro in ogni riga.
⊢⊢⌸⍨≠⊃⍤⊆¨⊢
Provalo online!
⊢
sull'argomento,
≠
usa i non spazi per ...
⊆¨
partizionare ogni elenco in un elenco di elenchi (rimuove gli spazi, mantiene le sequenze di non spazi),
⊃⍤
quindi mantieni il primo [di ciascuno] (ovvero i tag),
⊢⌸⍨
usali come chiavi per raggruppare ...
⊢
l'argomento
vim, 13 11 byte
:sor/\w\+/r
bugfix e byte save grazie a @Dingus!
Provalo online!
Scala, 26 byte
_.sortBy(_.split("]")(0))
Restituisce un List[String]
senza separatore in mezzo, ma è ordinato in base al tag.
Provalo in Scastie
Restituisce un Map[String,List[String]]
, 26 byte
_ groupBy(_.split("]")(0))
Prende un elenco di stringhe e restituisce a Map[List[String]]
dove le chiavi sono i tag ei valori sono i log associati a quel tag.
Provalo in Scastie
Soluzione precedente, 66 byte
_ groupBy{case s"[$t]$r"=>t}map(_._2 mkString "\n")mkString "\n"*2
Provalo in Scastie (per qualsiasi motivo, s
non funziona in TIO)
I log di ogni app sono separati da 2 newline (potrei essere in grado di salvare 2 byte se dovesse essere solo un carattere di nuova riga). L'input è un elenco di stringhe e l'output è una grande stringa.
05AB1E , 3 byte
Σ#¬
Input and Output è un elenco di log.
Spiegazione:
Σ#¬
Σ Sort by:
# Split (each log) by spaces
¬ Head (which is the tagname)
Ciò mantiene anche l'ordine dei registri, come richiesto.
Provalo online!
Retina 0.8.2 , 14 13 byte
O$`(\w+).* $1
Provalo online! Spiegazione: poiché non è richiesto alcun separatore di gruppo di output, le righe vengono semplicemente ordinate per tag dell'app, che si ottiene catturando la corrispondenza su \w+
e specificando $1
come chiave di ordinamento. L'ordinamento in Retina è stabile, quindi le righe con lo stesso prefisso manterranno il loro ordine. Modifica: salvato 1 byte grazie a @FryAmTheEggman per aver indicato un modo più semplice per abbinare il tag dell'app. Nota che sebbene la corrispondenza non includa l'interlinea [
, tutte le linee iniziano con [
, quindi ciò non influisce sul risultato dell'ordinamento.
AWK , 62 58 byte
Salvati 4 byte grazie a Dominic van Essen !!!
{a[$1][i++]=$0}END{for(k in a)for(j in a[k])print a[k][j]}
Provalo online!
Memorizza tutte le linee in una matrice associativa 2D a
. La prima chiave è il primo campo (separato da spazi). Quindi tutte le righe che iniziano con lo stesso campo vengono memorizzate insieme. La seconda chiave è un indice intero crescente. La parte più dettagliata è l' END
azione che stampa il contenuto di a
raggruppato per primo campo in ordine di apparizione.
Japt , 4 byte
Accetta l'input come un array di linee, produce un array 2D.
ü_¸g
Provalo
Io , 73 byte
method(i,i map(split first)unique map(I,i select(split first==I))flatten)
Provalo online!
Perl 6 , 16 byte
*.sort:{~m/\w+/}
Provalo online!
Ordina in base alla prima stringa di caratteri alfanumerici, che dovrebbe essere il nome dell'app
Python 3 , 148127 byte
a={}
try:
while 1:
b=input();c=b.split("]")[0]
if 1-(c in a):a[c]=[]
a[c]+=[b]
except:[print(e)for k in a for e in a[k]]
Provalo online!
V (vim) , 5 byte
úr/?]
Nota: quanto ?
sopra è al posto del byte non stampabile \$\text{\x}81\$ (il carattere di controllo "No Break Here").
Provalo online!
Si noti che questo funziona con la mancanza di spazi (anche uno subito dopo la prima ]
parentesi), con la presenza di []
parentesi nel messaggio di log, e con la presenza di un'applicazione senza tag, Provalo online!
Come?
úr/?]
ú - sort by:
r - with flag=r: use match (default behaviour is to use what's after the match)
/ - with the pattern:
? - (byte 83) a shortcut for .\{-}
. - match any character
\{-} - 0 or more times matching as few times as possible
] - match a literal ']' character
AutoHotkey, 74 byte
Loop,Read,f
{
s:=A_LoopReadLine
FileAppend,%s%`n,% StrSplit(s,"]","[")[1]
}
Legge da un file denominato f
e genera in più file in base al tag.
SimpleTemplate 0,84, 109 byte
Sì, è piuttosto lungo, ma fa il lavoro!
{@callexplode intoL EOL,argv.0}{@eachL}{@if_ matches"@^(\[.*\])@"M}{@setS.[M.1]S.[M.1],_,EOL}{@/}{@/}{@echoS}
Questo codice genera un array con <old content>, line, <end of line>
.
{@echoS}
appiattisce automaticamente l'array e lo visualizza.
Ungolfed:
Sì, è un casino, ma ecco una versione più pulita:
{@call explode into lines EOL, argv.0}
{@set storage null}
{@each lines as line}
{@if line matches "@^(\[.*\])@" match}
{@set storage.[match.1] storage.[match.1], line, EOL}
{@/}
{@/}
{@echo storage}
La funzione explode
è una funzione PHP standard, ma accessibile dalla mia lingua.
Puoi provarlo su: http://sandbox.onlinephpfunctions.com/code/9c66f8bacc6315ae56e7c193170e430f9cf9d902
C # (.NET Core) ,
181
162
160 byte
input.GroupBy(l=>l.Split()[0]).ToList().ForEach((g)=>{using(var sw = new StreamWriter(g.Key.Trim('[').Trim(']')+".log")){foreach(var v in g)sw.WriteLine(v);}});
Provalo online!
C # (Visual C # Interactive Compiler) , 179 byte
i=>i.GroupBy((l)=>{return l.Split(' ')[0];}).ToList().ForEach((g)=>{using(var sw = new StreamWriter(g.Key.Trim(new char[]{'[',']'})+".log")){foreach(var v in g)sw.WriteLine(v);}})
Provalo online!
Non sono sicuro che la prima soluzione sia conforme al code gulf, quindi la seconda soluzione utilizza un'espressione lambda.
Haskell, 37 byte
import Data.List
f=sortOn(head.words)
Provalo online!
Ruggine, 40 byte
|a|a.sort_by_key(|x|x.split("]").next())
Prende un riferimento mutevole a una porzione di stringhe e lo ordina.
Provalo nel parco giochi ruggine
Perl 5 -M5.10.0 -Msort = stabile, 53 byte
say sort{(split('\]',$a))[0]cmp(split('\]',$b))[0]}<>
Provalo online!