Dosyayı satır numarasına göre filtrele


17

Satır başına negatif olmayan bir tamsayı ve metin dosyası F olan bir dosya L verildiğinde, satır numarası L dosyasında görünen F'de yalnızca bu satırları tutmanın hızlı bir yolu nedir?

Misal:

$ cat L.txt
1
3

$ cat F.txt
Hello World
Hallo Welt
Hola mundo

$ command-in-question -x L.txt F.txt
Hello World
Hola mundo

Ben 500 milyon veya daha fazla giriş ile bir dosya L işleyebilir bir komut arıyorum; L dosyası sayısal olarak sıralanmıştır.

Not: Bir uygulama için yarı yoldayım command-in-questionama sadece bazı Unix araçlarını burada da kullanıp kullanamayacağımı merak ettim.


Güncelleme: Tüm cevaplar için teşekkürler, bugün çok şey öğrendim! Bir cevabı daha kabul etmek istiyorum, ama bu mümkün değil.


F dosyasında kaç satır var?
Peter.O

1
F'de L'de olduğu gibi en az satır vardır
miku

Yanıtlar:


8

İle Canlamlı hata mesajları atlayarak:

#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[]) {

    FILE *L;
    FILE *F;

    unsigned int to_print;
    unsigned int current = 0;
    char *line = NULL;
    size_t len = 0;

    if ((L = fopen(argv[1], "r")) == NULL) {
        return 1;
    } else if ((F = fopen(argv[2], "r")) == NULL) {
        fclose(L);
        return 1;
    } else {

        while (fscanf(L, "%u", &to_print) > 0) {
            while (getline(&line, &len, F) != -1 && ++current != to_print);
            if (current == to_print) {
                printf("%s", line);
            }
        }

        free(line);
        fclose(L);
        fclose(F);
        return 0;
    }
}

2
Buradaki en performanslı cevap bu. En azından testlerimde öyle. Vaka kimse ilgileniyor, ben gibi derlenmiş: xsel -bo | cc -xc - -o cselect. Ve işe yaradı - sadece iki libs'e ihtiyacı var.
mikeserv

1
Teşekkürler, bu harika! Umarım aldırmazsın, ama kodunu küçük bir araca tamamladım .
miku

1
@miku Devam et, yardım edebileceğime sevindim. LINE_MAXSürümünüzde artış olduğunu fark ettim , bu yüzden muhtemelen dosyalarınızda çok büyük satırlarla çalışıyorsunuz. A'yı getline(), satır boyutu sınırını kaldırmak için kullanan bir sürümle güncelledim .
FloHimself

@FloHimself, şey, tekrar teşekkürler :) Gerçekten de, bazı giriş satırları aşılabilir LINE_MAX, bu yüzden getlinedoğru görünüyor.
miku

10

Kullanırdım awk, ancak tüm içeriğini L.txtbellekte saklamam ve gereksiz karma aramalar yapmam ;-).

list=L.txt file=F.txt
LIST="$list" awk '
  function nextline() {
    if ((getline n < list) <=0) exit
  }
  BEGIN{
    list = ENVIRON["LIST"]
    nextline()
  }
  NR == n {
    print
    nextline()
  }' < "$file"

Tam olarak, karma haritaları denedim ve hafızayı aşacaklardı; bitsets size daha fazla tavan boşluğu alacak; ancak girdinin sıralandığı gerçeğini kullanarak, bu (boşluk) sorundan tamamen kurtulabilirsiniz.
miku

1
@Janis; bu sadece standart iyi kodlama uygulaması örneği değil: sabit kod değişmezlerini kullanmayın - değişkenleri kullanın ... (daha esnek ve daha az hata eğilimli ve bakımı daha kolay)
Peter.O

1
@ StéphaneChazelas: Bu ön-halka başlatma ihtiyacı n(olduğu gibi), aksi takdirde kaçırır, 1içindeL.txt
Peter.O

1
@ Peter.O, ayy, ben NR> = n ile ele almaya çalıştım, ama bu yanlıştı. Şimdi daha iyi olmalı.
Stéphane Chazelas

1
@Janis, fikir şu ki, eğer bu kod bir command-in-questionbetiğe gömülecekse, dosya adına kodu gömemezsiniz. -v list="$opt_x"awk tarafından yapılan ters eğik çizgi nedeniyle de çalışmaz. Bu yüzden burada ENVIRON kullanıyorum.
Stéphane Chazelas

10

grep -n | sort | sed | cut

(   export LC_ALL=C
    grep -n ''   | sort -t:  -nmk1,1 ./L - |
    sed /:/d\;n  | cut  -sd: -f2-
)   <./F

Bu , herhangi bir boyutta girdi ile oldukça hızlı bir şekilde çalışmalıdır (bazı zamanlanmış testler aşağıdadır) . Nasıl yapılacağına dair bazı notlar:

  • export LC_ALL=C
    • Aşağıdaki işlemin amacı, ./Fyığılmış dosyanın tamamını ./Llineno'nun dosyasıyla satır içine almak olduğundan , endişelenmemiz gereken tek karakter ASCII [0-9]basamakları ve :iki nokta üst üste işaretidir.
    • Bu nedenle, 128 olasılık setinde bu 11 karakteri bulma konusunda endişelenmek UTF-8'in başka şekilde dahil edilmesinden daha kolaydır.
  • grep -n ''
    • Bu, dizeyi LINENO:stdin'deki her satırın başına ekler - veya <./F.
  • sort -t: -nmk1,1 ./L -
    • sortihmaller hiç onun girdi dosyaları sıralamak ve bunun yerine etmek (doğru) onlar ön ayrımı olan varsaymaktadır ve -mbunları erges -numericallytemelde olası ötesinde bir şey yok sayarak, sıralı düzende -k1,1st meydana gelen -t:neyse kolon karakteri.
    • Bu, yapılması gereken geçici bir alan gerektirse de (bazı dizilerin ne kadar ayrı olabileceğine bağlı olarak) , uygun bir sıralama ile karşılaştırıldığında çok fazla gerekmeyecektir ve çok hızlı olacaktır, çünkü sıfır geri izlemeyi içerir.
    • sortherhangi bir lineno'nun ./Liçindeki ilgili satırlardan hemen önce geleceği tek bir akış çıkarır ./F. ./Lçizgileri her zaman önce gelir çünkü daha kısadırlar.
  • sed /:/d\;n
    • Geçerli satır bir /:/iki nokta üst üste ile deşleşirse çıkıştan alır. Aksi takdirde, geçerli ve ndahili satırı otomatik olarak yazdırın .
    • Ve böylece sedkuru erik sort, yalnızca iki nokta üst üste ve bir sonraki satırla eşleşmeyen sıralı satır çiftlerine veya yalnızca bir ./Lsonraki satırdan sonra bir satıra çıktı verir .
  • cut -sd: -f2-
    • cut -selimiter -d:dizelerinden en az birini içermeyen girdi çizgilerinin çıktılarından yukarı doğru baskı yapar ve böylece ./Lhatları tamamen budanır .
    • Bunu yapan hatlar için, ilk :kolonla sınırlandırılmış -falanı cutuzaktadır - ve böylece grepsokulan tüm linenolar gider .

küçük giriş testi

seq 5 | sed -ne'2,3!w /tmp/L
        s/.*/a-z &\& 0-9/p' >/tmp/F

... 5 satır numune girişi üretir. Sonra...

(   export LC_ALL=C; </tmp/F \
    grep -n ''   | sort -t:  -nmk1,1 ./L - |
    sed /:/d\;n  | cut  -sd: -f2-
)|  head - /tmp[FL]

... baskılar ...

==> standard input <==
a-z 1& 0-9
a-z 4& 0-9
a-z 5& 0-9

==> /tmp/F <==
a-z 1& 0-9
a-z 2& 0-9
a-z 3& 0-9
a-z 4& 0-9
a-z 5& 0-9

==> /tmp/L <==
1
4
5

daha büyük zamanlı testler

Birkaç oldukça büyük dosya oluşturdum:

seq 5000000 | tee /tmp/F |
sort -R | head -n1500000 |
sort -n >/tmp/L

... ve 5mil satırları /tmp/Fve 1.5mil rastgele seçilmiş satırları /tmp/L. Sonra yaptım:

time \
(   export LC_ALL=C
    grep -n ''   | sort -t:  -nmk1,1 ./L - |
    sed /:/d\;n  | cut  -sd: -f2-
)   <./F |wc - l

Yazdırdı:

1500000
grep -n '' \
    0.82s user 0.05s system 73% cpu 1.185 total
sort -t: -nmk1,1 /tmp/L - \
    0.92s user 0.11s system 86% cpu 1.185 total
sed /:/d\;n \
    1.02s user 0.14s system 98% cpu 1.185 total
cut -sd: -f2- \
    0.79s user 0.17s system 80% cpu 1.184 total
wc -l \
    0.05s user 0.07s system 10% cpu 1.183 total

(Oraya ters eğik çizgi ekledim)

Şu anda burada sunulan çözümler arasında, bunların en hızlısıdır, ancak yukarıda makinemde üretilen veri kümesine karşı çekildiğinde bir tanesidir. Diğerleri arasından sadece biri ikinci sırada yer almaya yaklaştı ve bu da meuh'un perl burada .

Bu hiçbir şekilde sunulan orijinal çözüm değildir - başkaları tarafından sunulan tavsiye / ilham sayesinde uygulama süresinin üçte birini düşürmüştür. Daha yavaş çözümler için gönderi geçmişine bakın (ama neden?) .

Ayrıca, sistemimin çoklu işlemci mimarisi ve bu boru hattındaki süreçlerin her birinin aynı anda yürütülmesi için değilse, diğer bazı cevapların çok daha iyi olabileceğini belirtmek gerekir. Hepsi aynı anda çalışır - her biri kendi işlemci çekirdeğinde - verilerin etrafında dolaşır ve bütünün küçük bir kısmını yapar. Oldukça havalı.

ama en hızlı çözüm ...

Ama en hızlı çözüm bu değil. Burada sunulan en hızlı çözüm, eller serbest, C programıdır . Aradım cselect. X panomuza kopyaladıktan sonra şöyle derledim:

xsel -bo | cc -xc - -o cselect

Sonra yaptım:

time \
    ./cselect /tmp/L /tmp/F |
wc -l

... ve sonuçlar ...

1500000
./cselect /tmp/L /tmp/F  \
    0.50s user 0.05s system 99% cpu 0.551 total
wc -l \
    0.05s user 0.05s system 19% cpu 0.551 total

1
Sen ile önemli ölçüde daha hızlı (neredeyse çabuk çok çekirdekli sistemlerde mayın gibi) yapabilirsiniz sed -ne'/:/!{n;p;}' | cut -d: -f2-yerinesed -ne'/:/!N;/\n/s/[^:]*://p'
Stéphane Chazelas

@ StéphaneChazelas - seds'yi değiştirirseniz daha iyi sonuçlar alabilirsiniz - sedBen kullanıyorum yadigar sed- sonuçlardaki aliasdeğeri görebilirsiniz time. Heirloom paketim bu arada, statik olarak TRE'ye dayanan regex uygulaması olan bir musl libc'ye karşı derlendi . Bunu GNU'ya geçirdiğimde sedve onsuz çalıştırdığımda cut, tamamlanma süresine (2,8 sn) tam bir saniye ekler - üçte birinden fazla artırır . Ve bu sadece benim sistemimdekinden sadece 0,3 sn daha hızlı.
mikeserv

1
sort -mnaksine sort -nmk1,1(burada test değil) bölme yapmak gerekmez gibi daha iyi olabilir
Stéphane Chazelas

@ StéphaneChazelas - evet, aynı şeyi düşündüm ve her şekilde denedim. -nsadece bir satırda ilk sayısal dize yapmak için spec'd olduğunu, bu yüzden düşündüm, tamam -mnveya -nmve ne nedenle olursa olsun, şimdiye kadar 2sec'in altına daldırılmış tek seferler tüm seçeneklerde olduğu gibi eklediğim zamandı. Bu garip - ve dün -milk başta bununla uğraşmamamın nedeni - Neyle ilgili olduğumu biliyordum, ama sadece bir tür otomatik optimizasyon işi olarak çalışmak gibiydi. İlginçtir, yadigar sadece geçerli sortbir -zdize uzunluğu seçeneği vardır -[cm]....
mikeserv

-nsatırdaki ilk sayısal dize değildir . Satırı bir sayı olarak kabul eder, bu yüzden abc 1230 olur. Bu nedenle, olduğundan daha az verimli olamaz-t: -k1,1
Stéphane Chazelas

9

Kullanacağım awk:

awk 'NR==FNR {a[$1]; next}; FNR in a' L.txt F.txt

Güncelleme: Performans ölçümleri yaptım; Bu sürüm, çok büyük veri kümeleriyle (belirtilen gereksinimlerde olduğu gibi) daha iyi ölçekleniyor gibi görünüyor, çünkü karşılaştırma çok hızlı ve hash tablosunu oluşturmak için gereken çabayı aşırı derecede telafi ediyor.


1
@miku; Evet, güzel ve kompakt bir çözüm. Ancak bir uyarı; hepsi awkbu kadar büyük veri setlerini işleyemeyebilir. - GNU kullanıyorum awkve sorun yok; 500 milyon satırlık veri ile test 7 dakika sürdü.
Janis

1
Bu oldukça yavaş (karşılaştırıldığında) real 16m3.468s- user 15m48.447s- sys 0m10.725s. 50.000.000 satır Lile 1/10 boyutunda 3,3 GB RAM testi kullanmıştır ; ve ile 500.000.000 hatları - vs Stéphane Chazelas' awk anser için zaman: - - - Ben hızlı kutusunu kullanarak değilim, ama karşılaştırma ilginçtir. Freal 2m11.637suser 2m2.748ssys 0m6.424s
Peter.O

@ Peter.O; Veriler için teşekkürler! İlişkili bir dizide (kendi test durumumda) yarım milyar satırın saklandığı göz önüne alındığında, daha yavaş bir hız beklenecekti . (Bu yüzden Stephane'nin teklifi için yukarıda "(+1)" yorumunu yaptım.) Bence bu kod deseni (basitliği nedeniyle!) Uygun bir seçenek ve özellikle daha az aşırı veri boyutları olan durumlarda yapar.
Janis

Kesinlikle uygulanabilir bir çözümdür. Kullandığım test verilerinde (5mil satır / 1.5mil L) seninki 4 saniyeden biraz fazla bir sürede tamamlandı - Stephane'ın cevabından sadece bir saniye sonra. Test setini oluşturmak için kullanılan kod benim cevabımda, ancak çoğunlukla sadece seqçıktı ve daha sonra L' de aynı küçük, rastgele seçilmiş bir altkümedir .
mikeserv

1
500 milyon satırlık veri dosyası boyutu ve 50 milyon ve anahtar dosya boyutu ile biraz daha performans ölçümleri yaptım. Dikkate değer bir gözlemle 500 milyon satır. Daha küçük anahtar dosyası ile süreler 4 dk (Stephane) ile 8 dk (Janis), daha büyük anahtar dosyasıyla ise 19 dk (Stephane) ile 12 dk (Janis).
Janis

3

Sadece bütünlük için: Stéphane Chazelas'ın cevabındaki mükemmel awk betiğini ve kos'un cevabındaki perl betiğini ancak tüm listeyi hafızada tutmadan perl'in awk'den daha hızlı olabileceği umuduyla birleştirebiliriz. (Args sırasını orijinal soruya uyacak şekilde değiştirdim).

#!/usr/bin/env perl
use strict;

die "Usage: $0 l f\n" if $#ARGV+1 != 2;
open(L,$ARGV[0]) or die "$ARGV[0]: $!";
open(F,$ARGV[1]) or die "$ARGV[1]: $!";

while(my $number = <L>){
    #chop $number;
    while (<F>) {
        if($. == $number){
            print;
            last;
        }
    }
}

Bu çok daha hızlı awk. Bu benimki kadar hızlı - Ben şimdi sadece üç kez test ettim ve benimki 5mil hat test setimi 1.8 ... saniyede ve her seferinde 1.9 ... saniyede ele aldığımda. Eğer önemsiyorsanız testset gen kodu benim cevabımda, ama asıl nokta çok iyi olmasıdır. Dahası, çıktı doğru - hala awkişi yapamıyorum ... Yine de, her iki cevabımız da FloHimself'ın utanç verici .
mikeserv

@mikeserv, farklı awks olmalı . Numunenizde gawk ile 1.4s (Janis 'için 4s), mawk ile 0.9s, bu perl çözeltisiyle 1.7s, kos ile 2.3s, seninle 4.5s (GNU sed) ve seninle 1.4s ( GNU sed) ve benim önerdiğim iyileşme (ve C çözeltisi için 0.5s).
Stéphane Chazelas

@mikeserv, ah! Tabii ki yaklaşımınızla, yerel bir fark yaratır. UFT-8'den C'ye geçerken burada 4.5s'den 2.3s'ye kadar
Stéphane Chazelas

3

Bunu yapmak için basit bir Perl betiği yazdım:

Usage: script.pl inputfile_f inputfile_f

#!/usr/bin/env perl

$number_arguments = $#ARGV + 1;
if ($number_arguments != 2) {
    die "Usage: script.pl inputfile_f inputfile_l\n";
}

open($f, '<', $ARGV[0])
    or die "$ARGV[0]: Not found\n";
open($l, '<', $ARGV[1])
    or die "$ARGV[1]: Not found\n";

@line_numbers = <$l>;

while ($line = <$f>) {
    $count_f ++;
    if ($count_f == @line_numbers[$count_l]) {
        print $line;
        $count_l ++;
    }
}
  • Yükler F.txt
  • Yükler L.txt
  • Her satırını L.txtbir diziye kaydeder
  • F.txtGeçerli satır numarasını ve geçerli dizi dizinini izleyerek satır satır okur ; F.txtgeçerli satır sayısını artırır ; eğer F.txtakım satır numarası geçerli dizi endeksine dizinin içeriğini maçları, bulunulan satırı yazdırır ve indeksi artırır

Maliyet ve karmaşıklık konuları :

Maliyeti göz önüne alındığında atamaları yapmak, N verilen karşılaştırma yapmak için maliyet ve çizgileri yazdırmak için maliyeti 1 satır sayısı olarak F.txtve N 2 satır sayısı olarak L.txt, whileen N'daki döngü çalışır 1 kez, 2N giden 1 + N 2 atamaları (tabii ki, N varsayılarak 1 > K 2 2N için) 1 karşılaştırmalar ve N 2 baskılar; Her işlem eşit eksiksiz olarak verilen, çalıştırmak için toplam maliyet whiledöngü 4N olan 1 + 2N 2 , O (N) senaryonun bir karmaşıklığına olan yol açar.

10 milyon satırlık giriş dosyasında test edin :

10 milyon hatları kullanarak F.txtrasgele 50-karakter uzunluğundaki çizgiler içeren dosyayı ve 10 milyon hatları L.txt10000000 1 kadar numara içeren dosyayı (en kötü durum senaryosu):

~/tmp$ for ((i=0; i<3; i++)); do time ./script.pl F.txt L.txt > output; done

real    0m15.628s
user    0m13.396s
sys 0m2.180s

real    0m16.001s
user    0m13.376s
sys 0m2.436s

real    0m16.153s
user    0m13.564s
sys 0m2.304s

2

Bu perl çözeltisi diğer awk veya perl çözeltilerinden% 20 kadar daha hızlıdır, ancak belli ki C'deki çözelti kadar hızlı değildir.

perl -e '
  open L, shift or die $!;
  open F, shift or die $!;
  exit if ! ($n = <L>);
  while (1) {
    $_ = <F>;
    next if $. != $n;
    print;
    exit if ! ($n = <L>);
  }
' -- L F

0
cat <<! >L.txt
1
3
!

cat <<! >F.txt
Hello World
Hallo Welt
Hola mundo
!

cmd(){
 L=$1 F=$2
 cat -n $F |
 join $L - |
 sed 's/[^ ]* //'
}

cmd L.txt F.txt
Hello World
Hola mundo

L.txt sıralandığı için join kullanabilirsiniz. F.txt'deki her satırı numaralandırın, iki dosyayı birleştirin ve ardından satır numarasını kaldırın. Büyük ara dosyalara gerek yoktur.

Aslında yukarıdakiler, tüm beyaz boşluğu tek bir boşlukla değiştirerek veri satırlarınızı değiştirecektir. Satırı sağlam tutmak için, verilerinizde görünmeyen bazı karakterleri sınırlayıcı olarak seçmeniz gerekir, örneğin "|". Cmd sonra

cmd(){
 L=$1 F=$2
 cat -n $F |
 sed 's/^ *//;s/\t/|/' |
 join -t'|' $L - |
 sed 's/[^|]*|//'
}

İlk sed, "cat -n" çıktısından önde gelen boşlukları kaldırır ve sekmenin yerini alır. İkinci sed, satır numarasını ve "|" öğesini kaldırır.


Korkarım bu daha büyük dosyalar üzerinde çalışmayacak. <10 satır gerekir. Aynı fikrim vardı ve denedim join L.txt <(nl F.txt )ama büyük dosyalar üzerinde çalışmaz. Siteye hoş geldiniz, bu arada, genellikle yeni kullanıcılardan bu kadar net ve iyi biçimlendirilmiş cevaplar almıyoruz!
terdon

@terdon, Evet, sayısal olarak sıralanmış girdilerle çalışabilen join/ commçalışamayan bir utanç .
Stéphane Chazelas

@terdon: Olası müşteriyi takip ettim (şimdi silindi) ve denedim join -t' ' <(<L.txt awk '{printf("%010s\n",$0)}') <(<F.txt awk '{printf("%010s %s\n",NR,$0)}') | cut -d' ' -f2-- Yavaştı ! - ve uygun 0 dolgulu tuşlarla hazırlanmış dosyaları beslediğimde bile join -t' ' L.txt F.txt | cut -d' ' -f2- , hala yavaştı (hazırlık süresi dahil değil) - awk@Janis'in cevabından daha yavaştı (burada her ikisi için de alınan gerçek zamanlar hakkında bir yorum gönderdim) onun ve @ StéphaneChazelas 'cevabı
Peter.O

@ Peter.O evet. Ben awks birini önler benzer bir yaklaşım denedim ama hem çalışması ve buna değer olmak için bir yol bulamadım.
terdon

@terdon ve diğerleri: gerçek zamanlı join+ awk printf işlemi substiturion olduğu real 20m11.663s user 19m35.093s sys 0m10.513s Stéphane Chazelas' v real 2m11.637s user 2m2.748s sys 0m6.424s kullanılarak L50 milyon hatları, F500 milyon hatları.
Peter.O

0

Tamlık için, joinçözüme yönelik başka bir girişim :

sed -r 's/^/00000000000000/;s/[0-9]*([0-9]{15})/\1/' /tmp/L | join <( nl -w15 -nrz /tmp/F ) - | cut -d' ' -f2-

Bu, birleştirilen satır numarası sütununu, önde gelen sıfırlarla sabit uzunluk olarak çalıştığından biçimlendirerek çalışır, böylece sayılar her zaman 15 basamak uzunluğunda olur. Sütun artık sözlük sıralaması olmaya zorlandığından, bu, normal sayısal sıralama düzeninden hoşlanmayan birleşme sorununu atlatır. nlF.txt dosyasına bu biçimdeki satır numaralarını eklemek için kullanılır. Ne yazık ki sedL.txt'deki numaralandırmayı yeniden biçimlendirmek için kullanılmalıdır.

Bu yaklaşım, @ mikeserv'in yöntemi kullanılarak oluşturulan test verileri üzerinde iyi çalışıyor gibi görünüyor. Ama yine de çok yavaş - c çözümü makinemde 60 kat daha hızlı. zamanın yaklaşık 2 / 3'ü sedve 1 / 3'ü join. Belki daha iyi bir sed ifadesi vardır ...


Tamam - ama neden tüm sıfırları öneriyoruz? Bunun için bir fikir edinmeye çalışıyorum. Ayrıca, nlsüper cool, ancak test edilmemiş girişlerde sağlam bir şekilde kullanamazsınız. Bu kadar havalı yapan şeylerden biri de mantıksal sayfa -d kaldırıcısı. Varsayılan olarak girişte yalnızca dizelerden oluşan :\` (ancak arkadaki mezardan w / hariç) herhangi bir satır varsa , art arda 1, 2, 3 veya üç kez, sayımlarınız biraz çıldırır. W / deney - oldukça temiz. Özellikle nl` 1 sınırlayıcı dize ve daha sonra başka bir w / 3 veya 2 ile bir çizgi okuduğunda ne olduğuna bir göz atın
mikeserv

0

Kabul edilen cevap C olduğundan, buraya bir python çözümü atmanın uygun olduğunu düşündüm:

# Read mask
with open('L.txt', 'r') as f:
    mask = [int(line_num) for line_num in f.read().splitlines()]

# Filter input file
filtered_lines = []
with open('F.txt', 'r') as f:
    for i, line in enumerate(f.read().splitlines()):
        if (i+1) in mask:
            filtered_lines.append(line)

# Write newly filtered file
with open('F_filtered.txt', 'w') as f:
    for line in filtered_lines:
        f.write('%s\n' % line)

Numpy gibi harici bir kütüphane kullanılıyorsa, bir çözüm daha da zarif görünecektir:

import numpy as np

with open('L.txt', 'r') as f:
    mask = np.array([int(line_num)-1 for line_num in f.read().splitlines()])

with open('F.txt', 'r') as f:
    lines = np.array(f.read().splitlines())
filtered_lines = lines[mask]

with open('F_filtered.txt', 'w') as f:
    for line in filtered_lines:
        f.write('%s\n' % line)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.