Desintercalar líneas de registro [duplicar]

Aug 18 2020

Ha heredado un servidor que ejecuta varias aplicaciones que generan el mismo registro.

Su tarea consiste en desintercalar las líneas del archivo de registro por fuente. Afortunadamente, cada línea comienza con una etiqueta que indica de qué aplicación es.

Registros

Cada línea se verá así:

[app_name] Something horrible happened!
  • Las etiquetas de las aplicaciones están siempre entre corchetes y solo contendrán caracteres alfanuméricos y guiones bajos.
  • Todas las líneas tendrán una etiqueta de aplicación al principio. No habrá espacios en blanco anteriores ni ningún otro carácter.
  • Siempre habrá al menos un espacio después de la etiqueta de la aplicación.
  • Las etiquetas de la aplicación no están vacías
  • Puede haber otros corchetes más adelante en cualquier línea dada.
  • Puede que haya o no un mensaje después de la etiqueta
  • El registro puede estar vacío
  • No hay límite para la cantidad de etiquetas de aplicaciones únicas que estarán presentes en el archivo.

Ejemplo

Un registro completo podría verse así:

[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

Que debería generar tres registros diferentes:

[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

No se le dan los nombres de las etiquetas de la aplicación con anticipación. Debe determinarlos solo analizando el archivo de registro.

Reglas y puntuación

  • Esto es code-golf , así que gana el código más corto.
  • Se aplican reglas estándar y lagunas
  • Utilice cualquier formato de E / S conveniente, siempre que cada línea de entrada esté representada como una cadena, no como una etiqueta + mensaje previamente analizado. Lista no exhaustiva de salidas permitidas:
    • Varios archivos nombrados después de cada etiqueta
    • Varias listas de cadenas
    • Una lista concatenada de cadenas que contienen líneas agrupadas por etiqueta con o sin separador (el separador no debe comenzar con una etiqueta)
    • Igual que el anterior, pero para stdout o un archivo.
  • El orden en el que se generan los registros separados es irrelevante; sin embargo, las líneas de registro dentro de cada grupo deben conservar el orden en el que se encontraron en el archivo original.

Respuestas

9 Noodle9 Aug 18 2020 at 03:22

Bash , 4 11 bytes

Se agregaron 7 bytes para corregir un error amablemente señalado por Shaggy .

sort -sk1,1

¡Pruébelo en línea!

Realiza una clasificación estable (el sargumento de la línea de comandos) basada en el primer campo ( k1,1) separado por espacios en blanco.

7 Giuseppe Aug 18 2020 at 01:35

R , 50 46 bytes

function(r)split(r,substr(r,1,regexpr("]",r)))

¡Pruébelo en línea!

Salidas como a listcon cada elemento named con [tag]. Cada elemento de la lista mantiene el orden dentro de su etiqueta. Devuelve una lista con nombre named list()vacía para una entrada vacía.

-2 bytes cada uno gracias a Robin Ryder y Dominic van Essen.

5 isaacg Aug 18 2020 at 04:48

Pyth , 3 bytes

ohc

¡Pruébelo en línea!

El formato de entrada es una lista de cadenas:

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

Cómo funciona el código:

  • o: Ordenar por

  • h: El primer elemento de

  • c: Cada cadena se divide en espacios

4 JonathanAllan Aug 18 2020 at 01:55

Python , 44 bytes

lambda a:sorted(a,key=lambda l:l.split()[0])

¡Pruébelo en línea!

La E / S suelta nos permite tomar y dar como resultado una lista de líneas. Como no tenemos que separar los grupos, el problema se reduce a realizar un tipo estable de las líneas en el prefijo de cada línea hasta el primer espacio, también split()se dividirán en algunos otros caracteres de espacio en blanco, pero ninguno puede estar presente en la parte de la etiqueta de la aplicación.

3 Adám Aug 18 2020 at 01:49

APL (Dyalog Extended) , 10 bytes ( SBCS )

Función de prefijo tácito anónimo. Toma una lista de listas de caracteres como argumento. Devuelve una matriz de listas de caracteres, con un registro en cada fila.

⊢⊢⌸⍨≠⊃⍤⊆¨⊢

¡Pruébelo en línea!

 en el argumento,

 utilizar los no espacios para ...

⊆¨ dividir cada lista en una lista de listas (elimina espacios, mantiene series de no espacios),

⊃⍤ luego conserve la primera [de cada] (es decir, las etiquetas),

⊢⌸⍨ utilícelos como claves para agrupar ...

 el argumento

3 nmjcman101 Aug 18 2020 at 03:14

vim, 13 11 bytes

:sor/\w\+/r

corrección de errores y ahorro de bytes gracias a @Dingus!

¡Pruébelo en línea!

3 user Aug 18 2020 at 01:28

Scala, 26 bytes

_.sortBy(_.split("]")(0))

Devuelve un List[String]sin separador en el medio, pero está ordenado por la etiqueta.

Pruébalo en Scastie


Devuelve a Map[String,List[String]], 26 bytes

_ groupBy(_.split("]")(0))

Toma una lista de cadenas y devuelve un Map[List[String]]donde las claves son las etiquetas y los valores son los registros asociados con esa etiqueta.

Pruébalo en Scastie


Solución anterior, 66 bytes

_ groupBy{case s"[$t]$r"=>t}map(_._2 mkString "\n")mkString "\n"*2

Pruébelo en Scastie (por el motivo que sea, sno funciona en TIO)

Los registros de cada aplicación están separados por 2 líneas nuevas (podría guardar 2 bytes si solo tuviera que ser el carácter de una línea nueva). La entrada es una lista de cadenas y la salida es una cadena grande.

2 SomoKRoceS Aug 18 2020 at 04:41

05AB1E , 3 bytes

Σ#¬

Entrada y salida es una lista de registros.

Explicación:

Σ#¬
Σ          Sort by:
 #         Split (each log) by spaces
  ¬        Head (which is the tagname)

Esto también mantiene el orden de los registros, según sea necesario.

¡Pruébelo en línea!

2 Neil Aug 18 2020 at 02:27

Retina 0.8.2 , 14 13 bytes

O$`(\w+).* $1

¡Pruébelo en línea! Explicación: Dado que no se requiere un separador de grupos de salida, las líneas simplemente se ordenan por etiqueta de aplicación, lo que se logra capturando la coincidencia \w+y especificando $1como clave de clasificación. Ordenar en Retina es estable, por lo que las líneas con el mismo prefijo mantendrán su orden. Editar: Guardado 1 byte gracias a @FryAmTheEggman por señalar una forma más fácil de hacer coincidir la etiqueta de la aplicación. Tenga en cuenta que aunque la coincidencia no incluye el encabezado [, todas las líneas comienzan con [, por lo que no afecta el resultado de la clasificación.

2 Noodle9 Aug 18 2020 at 03:42

AWK , 62 58 bytes

4 bytes guardados gracias a Dominic van Essen !!!

{a[$1][i++]=$0}END{for(k in a)for(j in a[k])print a[k][j]}

¡Pruébelo en línea!

Almacena todas las líneas en una matriz asociativa 2D a. La primera clave es el primer campo (separado por espacios en blanco). Entonces, todas las líneas que comienzan con el mismo campo se almacenan juntas. La segunda clave es un índice entero creciente. La parte más detallada es la ENDacción que imprime el contenido de aagrupado por primer campo en orden de aparición.

1 Shaggy Aug 18 2020 at 01:32

Japonés , 4 bytes

Toma la entrada como una matriz de líneas, genera una matriz 2D.

ü_¸g

Intentalo

1 Noname Aug 18 2020 at 07:14

Io , 73 bytes

method(i,i map(split first)unique map(I,i select(split first==I))flatten)

Try it online!

1 JoKing Aug 18 2020 at 21:44

Perl 6, 16 bytes

*.sort:{~m/\w+/}

Try it online!

Sorts by the first string of alphanumeric characters, which should be the app name

1 DanielH. Aug 18 2020 at 01:11

Python 3, 148127 bytes

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

Try it online!

1 JonathanAllan Aug 19 2020 at 01:02

V (vim), 5 bytes

úr/?]

Note: The ? above is in-place of the unprintable byte \$\text{\x}81\$ (the "No Break Here" control character).

Try it online!

Note that this works with a lack of spaces (even one directly after the first ] bracket), with the presence of [] brackets in the log message, and with the presence of an untagged application, Try it online!

How?

ú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
1 EngineerToast Aug 19 2020 at 03:09

AutoHotkey, 74 bytes

Loop,Read,f
{
s:=A_LoopReadLine
FileAppend,%s%`n,% StrSplit(s,"]","[")[1]
}

Reads from a file named f and outputs into multiple files based on the tag.

1 IsmaelMiguel Aug 19 2020 at 19:09

SimpleTemplate 0.84, 109 bytes

Yeah, it's pretty long, but does the job!

{@callexplode intoL EOL,argv.0}{@eachL}{@if_ matches"@^(\[.*\])@"M}{@setS.[M.1]S.[M.1],_,EOL}{@/}{@/}{@echoS}

This code generates an array with <old content>, line, <end of line>.

{@echoS} automatically flattens the array and displays it.


Ungolfed:

Yes, it's a mess, but here's a cleaner version:

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

The function explode is a standard PHP function, but accessible from my language.


You can try this on: http://sandbox.onlinephpfunctions.com/code/9c66f8bacc6315ae56e7c193170e430f9cf9d902

1 BlackPanther Aug 18 2020 at 20:56

C# (.NET Core), 181 162 160 bytes

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

Try it online!

C# (Visual C# Interactive Compiler), 179 bytes

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

Try it online!

I'm not sure the first solution is code gulf compliant, so the second solution uses a lambda expression.

1 corvus_192 Aug 20 2020 at 03:43

Haskell, 37 bytes

import Data.List
f=sortOn(head.words)

Try it online!

1 corvus_192 Aug 20 2020 at 03:57

Rust, 40 bytes

|a|a.sort_by_key(|x|x.split("]").next())

Takes a mutable reference to a slice of strings and sorts it.

Try it on the rust playground

DominicvanEssen Aug 18 2020 at 20:30

Perl 5 -M5.10.0 -Msort=stable, 53 bytes

say sort{(split('\]',$a))[0]cmp(split('\]',$b))[0]}<>

Try it online!