Domanda

Consideriamo i seguenti due file che sono leggermente diversi:

foo (vecchia versione):

<Line 1> a
<Line 2> b
<Line 3> c
<Line 4> d

foo (nuova versione):

<Line 1> a
<Line 2> e
<Line 3> b
<Line 4> c
<Line 5> f
<Line 6> d

Come si può vedere, i personaggi e e f vengono introdotti nel nuovo file.

Ho una serie di numeri di riga corrispondente al file più vecchio ... diciamo, 1, 3, e 4 (corrispondenti alle lettere a, c, e d).

C'è un modo per fare una mappatura tra questi due file, in modo che posso ottenere i numeri di riga dei personaggi corrispondenti nel file più recente?

.

per esempio, il risultato sarebbe:

Old file line numbers (1,3,4) ===> New File line numbers (1,4,6)

Purtroppo ho solo emacs (con un ediff di lavoro), Python, e WinMerge a mia disposizione.

È stato utile?

Soluzione

Quello che vi serve è un stringa algoritmo di ricerca in cui si dispone di più modelli (le linee dal vecchia versione di foo) che si desidera cercare all'interno di un testo (la nuova versione di foo). Rabin-Karp algoritmo è un algoritmo per questo tipo di operazione. Ho adattato al vostro problema:

def linematcher(haystack, needles, lineNumbers):
    f = open(needles)
    needles = [line.strip() for n, line in enumerate(f, 1) if n in lineNumbers]
    f.close()

    hsubs = set(hash(s) for s in needles)
    for n, lineWithNewline in enumerate(open(haystack), 1):
        line = lineWithNewline.strip()
        hs = hash(line)
        if hs in hsubs and line in needles:
            print "{0} ===> {1}".format(lineNumbers[needles.index(line)], n)

Supponendo tuoi due file sono chiamati old_foo.txt e new_foo.txt allora si potrebbe chiamare questa funzione in questo modo:

linematcher('new_foo.txt', 'old_foo.txt', [1, 3, 4])

Quando ho provato a sui dati è stampato:

1 ===> 1
3 ===> 4
4 ===> 6

Altri suggerimenti

Si può fare tutto in Emacs:

(defun get-joint-index (file-a index file-b)
  (let ((table (make-hash-table :test #'equal)))
    (flet ((line () (buffer-substring-no-properties
                     (point-at-bol) (point-at-eol))))
      (with-temp-buffer (insert-file file-b)
        (loop for i from 1 do (puthash (line) i table)
              while (zerop (forward-line))))
      (with-temp-buffer (insert-file file-a)
        (loop for i in index do (goto-line i)
              collect (gethash (line) table))))))

Per eseguire,

M -: (get-joint-index "/tmp/old" '(1 3 4) "/tmp/new")

-> (1 4 6)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top