Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]11136[/thread]

nur 3. spalte in datei einlesen

Leser: 2


<< |< 1 2 >| >> 11 Einträge, 2 Seiten
bmxy
 2008-01-14 11:22
#104683 #104683
User since
2008-01-10
7 Artikel
BenutzerIn
[default_avatar]
hi hab mal wieder ein problem.
hab in einer datei so eine art tabelle mit werten stehen. getrennt sind die werte durch leerzeichen. Nun möchte ich eine bestimmte spalte einlesen (z.B die 3te).
zurzeit mache ich das mit split. aber dabei werden ja die anderen spalten auch eingelesen und zumindestens kurzfristik gespeichert, was ja bei meinem problem unnötig ist. gibt es eine möglichkeit nur die eine spalte einzulesen?

danke für eure hilfe.
mfg bmxy
Taulmarill
 2008-01-14 11:41
#104684 #104684
User since
2004-02-19
1750 Artikel
BenutzerIn

user image
Code (perl): (dl )
$foo = ( split / /, $string )[2];

Das dürfte schon die optimale Variante sein. split ist intelligent genug, um zu erkennen, dass er hier nur bis zum Ende des dritten Wertes schauen muss.
$_=unpack"B*",~pack"H*",$_ and y&1|0& |#&&print"$_\n"for@.=qw BFA2F7C39139F45F78
0A28104594444504400 0A2F107D54447DE7800 0A2110453444450500 73CF1045138445F4800 0
F3EF2044E3D17DE 8A08A0451412411 F3CF207DF41C79E 820A20451412414 83E93C4513D17D2B
Linuxer
 2008-01-14 12:30
#104685 #104685
User since
2006-01-27
3890 Artikel
HausmeisterIn

user image
Code: (dl )
$foo = ( split / /, $string )[2];

Mir wäre es neu, dass split() hier nur bis zum dritten Wert splittet.
Soweit ich weiß, wird $string komplett gesplittet und eine Liste der Teile geliefert.
Aus dieser Liste wird dann durch ( )[2] das dritte Element ausgewählt.


Code (perl): (dl )
1
2
3
# gesuchte Spalte
$col_num = 3;
$foo = ( split( //, $string, $col_num+1 ) )[$col_num-1];


splittet $string in 4 Teile und liefert demnach eine Liste mit 4 Teilen. Von diesen vier Teilen wird nur der dritte genommen und $foo zugewiesen.
Die Teile 1 bis 3 sind wie gewünscht und Teil 4 enthält den ungeteilten Rest des Strings.

meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
renee
 2008-01-14 12:43
#104687 #104687
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Linuxer+2008-01-14 11:30:53--
Code (perl): (dl )
1
2
3
# gesuchte Spalte
$col_num = 3;
$foo = ( split( //, $string, $col_num+1 ) )[$col_num-1];


Aus [$col_num-1] noch [-2] machen, dann ist es in meinen Augen klarer, dass das vorletzte Element genommen werden soll und es ist zusätzlich noch schneller...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
renee
 2008-01-14 12:45
#104688 #104688
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Benchmark:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/perl

use strict;
use warnings;
use Benchmark qw(cmpthese);

my @array = (1..10);
my $test = 9;

cmpthese(
  10000000,
  {
     negativ => sub{ my $x = $array[-2] },
     minus   => sub{ my $x = $array[$test-1] },
  }
);


Code: (dl )
1
2
3
             Rate   minus negativ
minus 4000000/s -- -39%
negativ 6600660/s 65% --
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Taulmarill
 2008-01-14 12:49
#104690 #104690
User since
2004-02-19
1750 Artikel
BenutzerIn

user image
Linuxer+2008-01-14 11:30:53--
Code: (dl )
$foo = ( split / /, $string )[2];

Mir wäre es neu, dass split() hier nur bis zum dritten Wert splittet.
Soweit ich weiß, wird $string komplett gesplittet und eine Liste der Teile geliefert.
Aus dieser Liste wird dann durch ( )[2] das dritte Element ausgewählt.


perldoc -f split
When assigning to a list, if LIMIT is omitted, or zero, Perl supplies a LIMIT one larger than the number of variables in the list, to avoid unnecessary work.
$_=unpack"B*",~pack"H*",$_ and y&1|0& |#&&print"$_\n"for@.=qw BFA2F7C39139F45F78
0A28104594444504400 0A2F107D54447DE7800 0A2110453444450500 73CF1045138445F4800 0
F3EF2044E3D17DE 8A08A0451412411 F3CF207DF41C79E 820A20451412414 83E93C4513D17D2B
Taulmarill
 2008-01-14 12:59
#104692 #104692
User since
2004-02-19
1750 Artikel
BenutzerIn

user image
Ok, den obigen Abschnitt aus dem Perldoc habe ich anscheinend falsch interpretiert. Optimiert wird wohl nur, wenn direkt einer Liste von scalaren zugewiesen wird, nicht wenn man per ()[2] einen bestimmten Wert aus der Liste nimmt.

Müsste perl aber doch an sich relativ einfach selber optimieren können, oder?
$_=unpack"B*",~pack"H*",$_ and y&1|0& |#&&print"$_\n"for@.=qw BFA2F7C39139F45F78
0A28104594444504400 0A2F107D54447DE7800 0A2110453444450500 73CF1045138445F4800 0
F3EF2044E3D17DE 8A08A0451412411 F3CF207DF41C79E 820A20451412414 83E93C4513D17D2B
renee
 2008-01-14 13:00
#104693 #104693
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
@Taulmarill: Du weist es aber keiner x-elementigen Liste zu...

B::Deparse zeigt an, dass ein split TRENNER, STRING, 0 gemacht wird und da tritt das von Dir zitierte nicht in Kraft...

Code (perl): (dl )
1
2
3
4
5
6
7
#!/usr/bin/perl

use strict;
use warnings;

my $string = "Dies ist ein Test";
my $foo    = (split / /, $string)[2];


Code: (dl )
1
2
3
4
5
6
C:\>perl -MO=Deparse bench.pl
use warnings;
use strict 'refs';
my $string = 'Dies ist ein Test';
my $foo = (split(/ /, $string, 0))[2];
bench.pl syntax OK

OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Linuxer
 2008-01-14 13:17
#104694 #104694
User since
2006-01-27
3890 Artikel
HausmeisterIn

user image
Taulmarill+2008-01-14 11:49:04--
perldoc -f split
When assigning to a list, if LIMIT is omitted, or zero, Perl supplies a LIMIT one larger than the number of variables in the list, to avoid unnecessary work.


Danke, dieses Verhalten war mir nicht (mehr) bewusst.
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
betterworld
 2008-01-14 22:09
#104721 #104721
User since
2003-08-21
2614 Artikel
ModeratorIn

user image
Krass, das zitierte Verhalten von split kannte ich auch noch nicht. Um das auszunuetzen, koennte man es wohl so schreiben:
Code (perl): (dl )
my (undef, $foo) = split / /, $string;


Aber um mal zur eigentlichen Frage zu kommen:
Quote
aber dabei werden ja die anderen spalten auch eingelesen und zumindestens kurzfristik gespeichert, was ja bei meinem problem unnötig ist. gibt es eine möglichkeit nur die eine spalte einzulesen?

Man kann nicht nur eine einzelne Spalte einlesen, wenn man im Voraus nicht weiß, wie lang die Spalten sind. Stell Dir vor, jedes Zeichen in der Datei wäre ein Mensch und Du müsstest ihn anrufen, um rauszufinden, welchen Wert das Zeichen hat. Dann kommst Du auch nicht darum herum, jeden einzelnen Menschen anzurufen, sonst weißt Du nie, ob Du nicht irgendwo ein Leerzeichen überschlagen hast.

Wenn man allerdings im Voraus schon weiß, wie lang die Spalten sind, kann man mit Hilfe von seek und read auch einzelne Spalten auslesen. Das würde sich aber (vermute ich jetzt mal) erst dann lohnen, wenn die Spaltenlänge weit über der Block- oder sogar der Pagegröße läge, also sagen wir mal mindestens ein paar KB.

Dass man darauf achtet, dass split nicht zu viel splittet, wie oben diskutiert, fällt da wohl viel eher ins Gewicht.
Dass der Rest der Zeile nicht zu lange gespeichert wird, kann man durch geschickten Einsatz von my-Variablen erreichen. Naja, oder eben von $_, aber local nicht vergessen...
<< |< 1 2 >| >> 11 Einträge, 2 Seiten



View all threads created 2008-01-14 11:22.