2

У меня есть текстовый файл лекционных тем из моего класса физики, который выглядит следующим образом:

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

Я на самом деле храню его как Google Doc, так что я могу экспортировать его как CSV, ODS, XSLX и т.д. Вместо CSV.

Я хочу создать индекс, как вы могли бы увидеть в конце книги, перечисляя темы в алфавитном порядке по дате, например,

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

или если вы хотите стать модным:

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

Сначала я подумал об использовании LaTeX , но все пакеты индексации, похоже, идут по номеру страницы, а не по произвольной строке, такой как дата. Фактически, «MakeIndex предполагает, что все номера страниц являются либо арабскими, либо строчными римскими цифрами»; http://www.tex.ac.uk/ctan/indexing/makeindex/doc/makeindex.pdf. Более того, входной файл для makeindex должен быть списком с одной темой и номером страницы в строке; он просто выполняет сортировку и форматирование: http://www.troubleshooters.com/linux/lyx/makeindex.htm

Итак, программное обеспечение, которое я ищу, должно сделать это:

  1. Принять CSV, TSV или другой формат электронной таблицы. Это было бы идеально, но я бы согласился с текстовым форматом, который довольно легко можно было бы сгенерировать из файла электронной таблицы, например, путем подстановки с помощью awk или sed .
  2. Свяжите первую запись каждой строки (например, дату 1/14) с каждой из следующих записей (например, темы Galilean relavity , Minkowski space и т.д.).
  3. Сортировать все темы по всем датам в алфавитном порядке.
  4. Объедините темы, которые появляются более одного раза, в одну запись, перечисляя каждую дату, в которой тема появляется.
  5. Выведите результат в стандартном формате.

Мое единственное требование к программному обеспечению - чтобы оно работало в Linux.

Я не суетливый по поводу формата вывода; текстовый файл, LaTeX, HTML, odf и т. д. все в порядке, пока я могу распечатать бумажную копию.

3 ответа3

2

Как F# и awk решения хорошо работают с несколькими изменениями. Тем не менее, я решил пойти со следующим скриптом 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])

В этом случае item соответствует дате, а keys соответствуют темам. \dotfill - это разметка LaTeX для заполнения горизонтального пространства точками.

2

Вы против моно? Если нет, то получите F # интерактивный

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

и используйте следующий скрипт F # (вы также можете скомпилировать его)

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

Это приведет к созданию текстового файла:

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

Не совсем то, что вы хотите, но было бы легко изменить вышеприведенное, чтобы получить разметку из латекса. Просто измените строку

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

включить нужную разметку для каждой строки. К сожалению, у меня нет доступа к моно прямо сейчас, поэтому он протестирован с .NET.

2

Сценарии оболочки и великолепная команда 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] } }
'

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .