объединить несколько строк в одну строку по значению столбца - PullRequest
6 голосов
/ 15 июня 2011

У меня очень большой текстовый файл с разделителями табуляции. Многие строки в файле имеют одинаковое значение для одного из столбцов в файле. Я хочу поставить их в одну линию. Например:

a foo
a bar
a foo2
b bar
c bar2

После запуска скрипта оно должно выглядеть так:

a foo;bar;foo2
b bar
c bar2

как я могу сделать это либо в сценарии оболочки, либо в Python?

спасибо.

Ответы [ 6 ]

3 голосов
/ 15 июня 2011

С помощью awk вы можете попробовать это

{   a[$1] = a[$1] ";" $2 }
END { for (item in a ) print item, a[item] }

Так что, если вы сохраните этот скрипт awk в файле с именем awkf.awk и если ваш входной файл - ifile.txt, запустите скрипт

awk -f awkf.awk ifile.txt | sed 's/ ;/ /'

Сценарий sed предназначен для удаления ведущих;

Надеюсь, это поможет

2 голосов
/ 15 июня 2011
from collections import defaultdict

items = defaultdict(list)
for line in open('sourcefile'):
    key, val = line.split('\t')
    items[key].append(val)

result = open('result', 'w')
for k in sorted(items):
    result.write('%s\t%s\n' % (k, ';'.join(items[k])))
result.close()  

не проверено

1 голос
/ 15 июня 2011

Протестировано с Python 2.7:

import csv

data = {}

reader = csv.DictReader(open('infile','r'),fieldnames=['key','value'],delimiter='\t')
for row in reader:
    if row['key'] in data:
        data[row['key']].append(row['value'])
    else:
        data[row['key']] = [row['value']]

writer = open('outfile','w')
for key in data:
    writer.write(key + '\t' + ';'.join(data[key]) + '\n')
writer.close()
0 голосов
/ 15 июня 2011
#! /usr/bin/env perl

use strict;
use warnings;

# for demo only
*ARGV = *DATA;

my %record;
my @order;
while (<>) {
  chomp;
  my($key,$combine) = split;

  push @order, $key unless exists $record{$key};
  push @{ $record{$key} }, $combine;
}

print $_, "\t", join(";", @{ $record{$_} }), "\n" for @order;

__DATA__
a foo
a bar
a foo2
b bar
c bar2

Вывод (с табуляциями, преобразованными в пробелы, потому что переполнение стека прерывает вывод):

a       foo;bar;foo2
b       bar
c       bar2
0 голосов
/ 15 июня 2011

Perl способ сделать это:

#!/usr/bin/perl 
use strict;
use warnings;
use Data::Dumper;

open my $fh, '<', 'path/to/file' or die "unable to open file:$!";
my %res;
while(<$fh>) {
    my ($k, $v) = split;
    push @{$res{$k}}, $v;
}
print Dumper \%res;

выход:

$VAR1 = {
      'c' => [
               'bar2'
             ],
      'a' => [
               'foo',
               'bar',
               'foo2'
             ],
      'b' => [
               'bar'
             ]
    };
0 голосов
/ 15 июня 2011
def compress(infilepath, outfilepath):
    input = open(infilepath, 'r')
    output = open(outfilepath, 'w')
    prev_index = None

    for line in input:
        index, val = line.split('\t')
        if index == prev_index:
            output.write(";%s" %val)
        else:
            output.write("\n%s %s" %(index, val))
    input.close()
    output.close()

Не проверено, но должно работать. Пожалуйста, оставьте комментарий, если есть какие-либо проблемы

...