Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
一个Perl脚本,用于处理CSV文件,聚合分布在多个记录上的属性_Perl_Csv - Fatal编程技术网

一个Perl脚本,用于处理CSV文件,聚合分布在多个记录上的属性

一个Perl脚本,用于处理CSV文件,聚合分布在多个记录上的属性,perl,csv,Perl,Csv,对不起,这个模糊的问题,我正在努力思考如何更好地表达它 我有一个CSV文件,看起来有点像这样,只是大了很多: 550672,1 656372,1 766153,1 550672,2 656372,2 868194,2 766151,2 550672,3 868179,3 868194,3 550672,4 766153,4 第一列中的值是ID号,第二列可以描述为属性(因为缺少更好的单词…)。ID号550672的属性为1,2,3,4。有人能告诉我如何开始解决如何为所有ID号生成这样的字符串吗?我

对不起,这个模糊的问题,我正在努力思考如何更好地表达它

我有一个CSV文件,看起来有点像这样,只是大了很多:

550672,1
656372,1
766153,1
550672,2
656372,2
868194,2
766151,2
550672,3
868179,3
868194,3
550672,4
766153,4
第一列中的值是ID号,第二列可以描述为属性(因为缺少更好的单词…)。ID号550672的属性为1,2,3,4。有人能告诉我如何开始解决如何为所有ID号生成这样的字符串吗?我的理想输出是一个新的csv文件,它看起来像:

550672,1;2;3;4
656372,1;2
766153,1;4
等等


我是一个非常喜欢Perl的婴儿(只有3天大!),所以我真的很欣赏方向,而不是一个彻底的解决方案,我决心学习这些东西,即使这需要我的余生!我已经尽我所能亲自调查过了,尽管我认为我一直被不知道真正要寻找什么所困扰。我能够读入和解析CSV文件(我甚至可以删除重复的值!),但对我来说,这就是它真正的落脚点。任何帮助都将不胜感激

好的,在perl中以stdin的形式打开文件,假设每行有两列,然后使用左列作为哈希标识符遍历所有行,并将右列收集到哈希键指向的数组中。在输入文件的末尾,您将得到一个数组的散列,因此对其进行迭代,打印一个散列键和分配的数组元素,这些元素之间用“;”或任何其他符号分隔

给你

dtpwmbp:~ pwadas$ cat input.txt 
550672,1
656372,1
766153,1
550672,2
656372,2
868194,2
766151,2
550672,3
868179,3
868194,3
550672,4
766153,4
dtpwmbp:~ pwadas$ cat bb2.pl 
#!/opt/local/bin/perl

my %hash;
while (<>)
{
    chomp;
    my($key, $value) = split /,/;
    push @{$hash{$key}} , $value ;
}

foreach my $key (sort keys %hash)
{
     print $key . "," . join(";", @{$hash{$key}} ) . "\n" ;
}
dtpwmbp:~ pwadas$ cat input.txt | perl -f bb2.pl 
550672,1;2;3;4
656372,1;2
766151,2
766153,1;4
868179,3
868194,2;3
dtpwmbp:~ pwadas$
dtpwmbp:~pwadas$cat input.txt
550672,1
656372,1
766153,1
550672,2
656372,2
868194,2
766151,2
550672,3
868179,3
868194,3
550672,4
766153,4
dtpwmbp:~pwadas$cat bb2.pl
#!/opt/local/bin/perl
我的%hash;
而()
{
咀嚼;
我的($key,$value)=拆分/,/;
push@{$hash{$key}},$value;
}
foreach my$键(排序键%hash)
{
打印$key.,“.join(;”,@{$hash{$key})。“\n”;
}
dtpwmbp:~pwadas$cat input.txt | perl-f bb2.pl
550672,1;2.3.4.
656372,1;2.
766151,2
766153,1;4.
868179,3
868194,2;3.
dtpwmbp:~pwadas$

首先是寻找方法而不是解决方案的道具。 正如您可能已经在perl中发现的那样,有多种方法可以做到这一点

我将采取的办法是:

use strict;  # will save you big time in the long run

my %ids      # Use a hash table with the id as the key to accumulate the properties
open a file handle on csv or die
while (read another line from the file handle){
  split line into ID and property variable  # google the split function
  append new property to existing properties for this id in the hash table  # If it doesn't exist already, it will be created
}

foreach my $key (keys %ids) {
  deduplicate properties
  print/display/do whatever you need to do with the result
}
这种方法意味着您需要在整个集合上迭代两次(在内存中迭代一次),因此取决于数据集的大小,这可能是一个问题。 一种更复杂的方法是在初始步骤中使用哈希表中的哈希表来执行重复数据消除,但这取决于您希望/需要以多快的速度使其工作,在第一个实例中可能不值得

退房 有关如何执行重复数据消除的讨论。

另一种(不是perl)方法,顺便说一句,它更简短、更优雅:

#!/opt/local/bin/gawk -f

BEGIN {FS=OFS=",";}

NF > 0 { IDs[$1]=IDs[$1] ";" $2; }

END { for (i in IDs) print i, substr(IDs[i], 2); }
第一行(指定解释器后)将输入字段分隔符和输出字段分隔符设置为逗号。第二行检查我们有超过零个字段,如果您这样做,它将ID($1)编号作为键,将$2作为值。您可以对所有行执行此操作


END语句将按未指定的顺序打印这些对。如果您想对它们进行排序,您必须选择
asorti
gnu awk函数,或者将此代码段的输出与管道连接到
sort-t,-k1n,1n

我认为最好是为您提供一个工作程序,而不是一些提示。提示只能带您到目前为止,如果您花时间理解此代码,它将为您提供良好的学习体验

最好在处理CSV数据时使用,因为所有调试都已为您完成

use strict;
use warnings;

use Text::CSV;

my $csv = Text::CSV->new;

open my $fh, '<', 'data.txt' or die $!;
my %data;
while (my $line = <$fh>) {
  $csv->parse($line) or die "Invalid data line";
  my ($key, $val) = $csv->fields;
  push @{ $data{$key} }, $val
}

for my $id (sort keys %data) {
  printf "%s,%s\n", $id, join ';', @{ $data{$id} };
}

非常感谢您的快速回复,我一直在阅读有关hash的文章,并怀疑它可能会起作用。我会陷入阅读这些元素的困境。如果你不介意,如果我再次陷入困境,我能回到你身边吗?再次非常感谢(我想点击向上箭头说你的答案很有用,但不幸的是,我似乎需要更多的代表!)请注意,这样的方法是有效的。在某种程度上自动连接重复的关键点。你可以使用一些Text::CSV模块,但是其他人可以使用一行代码:)数组的散列,等等,并不像你在perl中希望的那样简单,看看amon在这篇文章中的答案,并阅读链接文档:我认为我不能像你编码的那样快速键入。。。。有一天。。。有一天。。。再次感谢,这里有很多新的术语需要我学习-我期待着学习!哈哈,实际上,保存并预编一个要粘贴的文本,每行有四个空格,以便在粘贴到这里时将其标记为代码,这比编码花费了更多的时间和点击该死的MBP;-)thx:)嘎!我再次希望我能给你一支向上的箭!这很有帮助,非常感谢。很好的描述,我将彻底地了解这一点-真的很喜欢学习这些东西!研究如何使用一些csv模块<代码>文本::CSV是我的最爱。感谢您编辑我的问题,以获得正确的格式,我将确保以后我会遵守!我同意有时候最好的学习方法是以身作则,你能抽出时间为我写下这篇文章真是太好了,我期待着解构它来理解它!编辑:这很好,谢谢你。谢谢你的建议-虽然我不确定我的大脑是否足够大,可以同时使用两种编程语言!感谢您的回答,尽管我必须承认,在我目前的perl知识水平下,理解这样的一行程序是非常具有挑战性的。然而,我确实感到惊奇的是,我的问题的解决方案可以压缩成这样简洁的东西!事实上,我认为您的回答很有帮助,因为它演示了用这么短的代码可以实现什么,谢谢。
550672,1;2;3;4
656372,1;2
766151,2
766153,1;4
868179,3
868194,2;3
perl -F"," -ane 'chomp($F[1]);$X{$F[0]}=$X{$F[0]}.";".$F[1];if(eof){for(keys %X){$X{$_}=~s/;//;print $_.",".$X{$_}."\n"}}'