Générer un index alphabétique à partir d'une feuille de calcul

2

J'ai un fichier texte de sujets de cours de mon cours de physique qui ressemble à ceci:

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

En fait, je le stocke sous le nom de Google Doc afin de pouvoir l'exporter au format tsv, ods, xslx, etc. au lieu d'un fichier csv.

Je souhaite générer un index, comme vous le verrez à la fin d'un livre, en répertoriant les sujets par ordre alphabétique par date, par exemple.

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

ou si vous voulez avoir envie:

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

J'ai d'abord pensé à utiliser LaTeX, mais les packages d’indexation semblent tous aller par numéro de page, et non par une chaîne arbitraire comme une date. En fait, "MakeIndex suppose que tous les numéros de page sont des chiffres arabes ou des chiffres latins minuscules;" http://www.tex.ac.uk/ctan/indexing/makeindex/doc/makeindex.pdf . De plus, le fichier d’entrée pour makeindex doit être une liste avec un sujet et un numéro de page par ligne; il se contente de faire le tri et le formatage: http://www.troubleshooters.com/linux/lyx/makeindex.htm

Donc, le logiciel que je cherche a besoin de faire ceci:

  1. Acceptez un format de fichier csv, tsv ou autre. Ce serait idéal, mais je serais d'accord avec un format de texte qui pourrait être assez facilement généré à partir d'un fichier de feuille de calcul, par exemple. par substitutions avec awk ou sed.
  2. Associez la première entrée de chaque ligne (par exemple la date 1/14 ) avec chacune des entrées suivantes (par exemple, les rubriques Galilean relavity, Minkowski space, etc.).
  3. Triez tous les sujets pour toutes les dates par ordre alphabétique.
  4. Combinez les sujets qui apparaissent plus d'une fois dans une seule entrée, en répertoriant chaque date d'affichage du sujet.
  5. Afficher le résultat au format standard.

Ma seule exigence pour le logiciel est qu’il fonctionne sous Linux.

Je ne suis pas pointilleux sur le format de sortie; Les fichiers texte, LaTeX, HTML, ODF, etc. me conviennent, dans la mesure où je peux imprimer une copie papier.

Nathaniel M. Beaver
la source

Réponses:

2

Êtes-vous opposé à mono? Si non, alors obtenir F # interactive

http://fsharp.org/use/linux/

et utilisez le script F # suivant (vous pouvez aussi le compiler)

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

Cela produirait un fichier texte:

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

Pas exactement ce que vous voulez, mais il serait facile de modifier ce qui précède pour produire un balisage au latex. Il suffit de modifier la ligne

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

d'inclure le marquage souhaité pour chaque ligne. Malheureusement, je n'ai pas accès au mono dès maintenant, donc c'est testé avec .NET.

jizugu
la source
J'ai eu du mal à compiler à partir des sources, j'ai donc installé le paquet ici: [ fsxplat.codeplex.com/releases/view/55463] . Ça dit error FS0222: Files in libraries or multiple-file applications must begin with a namespace or module declaration, e.g. 'namespace SomeNamespace.SubNamespace' or 'module SomeNamespace.SomeModule'
Nathaniel M. Beaver
essayez d'ajouter "programme de module" en haut du fichier (sans guillemets)
jizugu
generate-index.fs(22,41): error FS0001: This expression was expected to have type string [] but here has type seq<string>
Nathaniel M. Beaver
Voici la ligne 22: let datestr = String.Join (", ",dates). dates est en position (22,41)
Nathaniel M. Beaver
try: let datestr = String.Join (",", dates | & gt; Seq.toArray)
jizugu
2

Shell scripting et le glorieux awk commander:

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] } }
'
Ramillete
la source
Il a fallu supprimer les deux virgules à la fin de la ligne 1 pour éviter une ligne à clé nulle dans la sortie.
Ramillete
Pouvez awk trier la sortie? Pour le moment, je dois le trier par ordre alphabétique. En outre, à quel point serait-il difficile d'éliminer les doubles espaces après le sujet? (En outre, la première ligne renvoie toutes les dates, donc je le filtre avec tail -n +2.)
Nathaniel M. Beaver
2

Les deux F# et awk les solutions fonctionnent bien avec quelques ajustements. Cependant, j'ai décidé d'utiliser le script python suivant:

#!/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])

Dans ce cas, item correspond à une date, et keys correspondent à des sujets. le \dotfill est le balisage LaTeX pour remplir un espace horizontal avec des points.

Nathaniel M. Beaver
la source