Gerar um índice alfabético a partir de uma planilha

2

Eu tenho um arquivo de texto de tópicos de aula da minha aula de física que se parece com isso:

1/14,Galilean relativity,Einsteinian relativity,Minkowski space,Henri Poincare,,
1/16,Lorentz transformations,Velocity transformations,Proper time,Light aberration,Lorentz tensors formalism,Minkowski space
1/23,Lorentz boost,Lorentz group,Poincare group,contravariant tensor,covariant tensor,d'Alembertian

Na verdade, eu o armazeno como o Google Doc, então eu poderia exportá-lo como um tsv, ods, xslx, etc. em vez de um csv.

Eu quero gerar um índice como você veria no final de um livro, listando os tópicos em ordem alfabética por data, por exemplo

d'Albertian 1/23
... (more entries)
Minkowski space 1/14 1/16
... (more entries)
Velocity transformations 1/16

ou se você quiser se interessar:

d'Albertian ................. 1/23
... (more entries)
Minkowski space ............. 1/14, 1/16
... (more entries)
Velocity transformations .... 1/16

Primeiro pensei em usar LaTeX , mas todos os pacotes de indexação parecem ter um número de página, não uma string arbitrária como uma data. Na verdade, "o MakeIndex assume que todos os números de página são numerais romanos em árabe ou em letras minúsculas"; link . Além disso, o arquivo de entrada para makeindex deve ser uma lista com um tópico e número de página por linha; ele apenas faz a classificação e a formatação: link

O software que estou procurando precisa fazer isso:

  1. Aceite um formato csv, tsv ou outro formato de planilha. Isso seria ideal, mas eu ficaria bem com um formato de texto que poderia ser facilmente gerado a partir de um arquivo de planilha, por exemplo por substituições com awk ou sed .
  2. Associe a primeira entrada de cada linha (por exemplo, a data 1/14 ) a cada uma das entradas a seguir (por exemplo, os tópicos Galilean relavity , Minkowski space , etc.).
  3. Classifique todos os tópicos para todas as datas em ordem alfabética.
  4. Combine os tópicos que aparecem mais de uma vez em uma única entrada, listando todas as datas em que o tópico é exibido.
  5. Envie o resultado como um formato padrão.

Meu único requisito para o software é que ele seja executado no Linux.

Eu não sou muito exigente com o formato de saída; arquivo de texto, LaTeX, HTML, odf, etc. estão bem por mim, contanto que eu possa imprimir uma cópia em papel.

    
por Nathaniel M. Beaver 25.04.2013 / 19:26

3 respostas

2

As soluções F# e awk funcionam bem com alguns ajustes. No entanto, decidi usar o seguinte script python:

#!/usr/bin/env python
import csv, sys
mydict = {}
for line in open(sys.argv[1],'r'):
    tokens = line.strip().split(',')
    item, keys = tokens[0], tokens[1:]
    for key in keys:
        if key != '':
            # If the key is already in the dictionary,
            # just add it to the set, otherwise make an
            # empty set to add the item to.
            mydict.setdefault(key, set()).add(item)
for key in sorted(mydict.keys(), key=str.lower):
    print key + ' \dotfill ' + ', '.join(mydict[key])

Nesse caso, item corresponde a uma data e keys correspondem a tópicos. A \dotfill é a marcação LaTeX para preencher espaço horizontal com pontos.

    
por 26.04.2013 / 08:07
2

Você se opõe ao mono? Se não, então pegue F # interativo

link

e use o seguinte script F # (você também pode compilá-lo)

open System
open System.IO

let inputFile = "inputFile.csv"
let outputFile = "out.txt"

File.ReadAllLines(inputFile)
|> Seq.filter (fun i -> i.Length > 0)
|> Seq.collect
    (fun i ->
        let fields = i.Split(',')
        let date = fields.[0]
        fields.[1..] |> Array.map (fun entry -> date,entry)
    )
|> Seq.groupBy snd
|> Seq.sortBy (fun (entry,_) -> entry.ToUpper())
|> Seq.filter (fun (entry,_) -> entry <> "")
|> Seq.map 
    (fun (entry,dates) ->
        let dates = dates |> Seq.map fst |> Seq.sort
        let datestr = String.Join (", ",dates)
        String.Format("{0} ........ {1}", entry, datestr)
    )
|> (fun i -> File.WriteAllLines(outputFile,i))

Isso produziria um arquivo de texto:

contravariant tensor ........ 1/23
covariant tensor ........ 1/23
d'Alembertian ........ 1/23
Einsteinian relativity ........ 1/14
Galilean relativity ........ 1/14
Henri Poincare ........ 1/14
Light aberration ........ 1/16
Lorentz boost ........ 1/23
Lorentz group ........ 1/23
Lorentz tensors formalism ........ 1/16
Lorentz transformations ........ 1/16
Minkowski space ........ 1/14, 1/16
Poincare group ........ 1/23
Proper time ........ 1/16
Velocity transformations ........ 1/16

Não é exatamente o que você quer, mas seria fácil modificar o código acima para produzir marcação de látex. Apenas modifique a linha

String.Format("{0} ........ {1}", entry, datestr)

para incluir a marcação desejada para cada linha. Infelizmente eu não tenho acesso a mono neste exato momento, então é testado com .NET.

    
por 25.04.2013 / 19:59
2

Script de shell e o glorioso comando awk :

awk -F, '
  { for (i=2;i<=NF;i++) { subject_dates[$i]=subject_dates[$i] " " $1 } }
  END { for (idx in subject_dates) { print idx, subject_dates[idx] } }
'
    
por 25.04.2013 / 21:37