как получить уникальные значения из повторяющегося списка значений - PullRequest
3 голосов
/ 12 февраля 2011

Мне нужно проанализировать большой файл журнала (плоский файл), который содержит два столбца значений (столбец-A, столбец-B).

Значения в обоих столбцах повторяются.Мне нужно найти для каждого уникального значения в столбце-A, мне нужно найти набор значений столбца-B.

Это можно сделать с помощью команды оболочки unix или вам нужно написать какой-нибудь скрипт на perl или python?Как это можно сделать?

Пример:

xxxA 2
xxxA 1
xxxB 2
XXXC 3
XXXA 3
xxxD 4

вывод:

xxxA - 2,1,3
xxxB - 2
xxxC - 3
xxxD - 4

Ответы [ 7 ]

5 голосов
/ 12 февраля 2011

Perl 'one-liner' предназначен / расширен, чтобы все помещалось в окне:

$ perl -F -lane '

      $hash{ $F[0] }{ $F[1] }++;
  } END {

      for my $columnA ( keys %hash ) {

          print $columnA, " - ", join( ",", keys %$hash{$columnA} ), "\n";
      }
  '

Объяснение последует, если я увижу согласованную попытку со стороны оригинального плаката.

3 голосов
/ 12 февраля 2011

Я бы использовал словари Python, где ключи словаря являются значениями столбца A, а значения словаря являются встроенными в Python Тип набора содержит значения столбца B

def parse_the_file():
    lower = str.lower
    split = str.split
    with open('f.txt') as f:
        d = {}
        lines = f.read().split('\n')
        for A,B in [split(l) for l in lines]:
            try:
                d[lower(A)].add(B)
            except KeyError:
                d[lower(A)] = set(B)

        for a in d:
            print "%s - %s" % (a,",".join(list(d[a])))

if __name__ == "__main__":
    parse_the_file()

Преимущество использованиясловарь - это то, что у вас будет один словарный ключ для каждого столбца.Преимущество использования набора состоит в том, что у вас будет уникальный набор значений столбца B.

Замечания по эффективности:

  • Использование try-catch более эффективно, чем использование оператора if \ else для проверки начальных случаев.
  • Оценка и назначениефункции str вне цикла более эффективны, чем простое их использование внутри цикла.
  • В зависимости от соотношения новых значений A и повторного появления значений A в файле, вы можете рассмотреть возможность использования a = lower(A)перед оператором try catch
  • я использовал функцию, поскольку доступ к локальным переменным в Python более эффективен, чем к глобальным переменным
  • Некоторые из этих советов по производительности взяты из здесь

Тестирование кода выше на вашем входном примере дает:

xxxd - 4
xxxa - 1,3,2
xxxb - 2
xxxc - 3
1 голос
/ 13 февраля 2011

Версия простого Perl:

#!/usr/bin/perl

use strict;
use warnings;

my (%v, @row);

foreach (<DATA>) {
        chomp;
        $_ = lc($_);
        @row = split(/\s+/, $_);
        push( @{ $v{$row[0]} }, $row[1]);
} 

foreach (sort keys %v) {
        print "$_ - ", join( ", ", @{ $v{$_} } ), "\n";
}

__DATA__
xxxA 2
xxxA 1
xxxB 2
XXXC 3
XXXA 3
xxxD 4

Не фокусируется на именах переменных.Из примера я вижу, что они не чувствительны к регистру.

1 голос
/ 12 февраля 2011

Вы можете использовать эту простую мультикарту:

class MultiMap(object):
    values = {}

    def __getitem__(self, index):
        return self.values[index]
    def __setitem__(self, index, value):
        if not self.values.has_key(index):
            self.values[index] = []
        self.values[index].append(value)
    def __repr__(self):
        return repr(self.values)

Смотрите это в действии: http://codepad.org/xOOrlbnf

0 голосов
/ 23 сентября 2011

Использование Perl oneliner:

perl -lane'$F[0]=~s/.../lc$&/e;exists$s{$F[0]}and$s{$F[0]}.=",$F[1]"or push@v,$F[0]and$s{$F[0]}=$F[1]}{print"$_ $s{$_}"for@v'

Вы можете удалить $F[0]=~s/.../lc$&/e;, если ваш ключ чувствителен к регистру (что не соответствует действительности в ваших тестовых данных), или использовать $F[0]=lc$F[0]; или $F[0]=uc$F[0];, если можетеобъедините ваш ключ в нижний или верхний регистр.

0 голосов
/ 12 февраля 2011

while() {

($key, $value) = split / /, $_;

$hash{lc($key)} = 1;

push(@array, "$key$value");

}

foreach $key (sort keys %hash) {

@arr = (grep /$key/i, @array);

chomp(@arr);

$val = join (", ", @arr);

$val =~ s#$key##gi; 

print "$key\t$val\n";

}
0 голосов
/ 12 февраля 2011

f = """xxxA 2
xxxA 1
xxxB 2
XXXC 3
XXXA 3
xxxD 4"""


d = {}

for line in f.split("\n"):
    key, val = line.lower().split()
    try:
        d[key].append(val)        
    except KeyError:
        d[key] = [val]


print d

Python

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...