Декодирование шаблона - PullRequest
1 голос
/ 07 января 2012

Мне нужна небольшая помощь в следующем.У меня есть такой файл данных:

0 0    # <--- Group 1 -- 1 house (0) and 1 room (0)

0 0    # <--- Group 2 -- 2 houses (0;1) and 3,2 rooms (0,1,2;0,1)
0 1
0 2    
1 0    # <--- house 2 in Group 2, with the first room (0)
1 1    # <--- house 2 in Group 2, with the second room (1)

0 0    # <--- Group 3
0 1    # <--- house 1 in Group 3, with the second room (1)
0 2

0 0    # <--- Group 4
1 0    # <--- house 2 in Group 4, with one room only (0)
2 0
3 0    # <--- house 4 in Group 4, with one room only (0)

0 0    # <--- Group 5

0 0    # <--- Group 6

Есть несколько случаев, на которые нужно ответить:

В примере есть группы;существует группа, если она отделена новыми строками от другой, поэтому в этом случае мы имеем 6 групп.Мы должны определить следующее

Получить фактический номер (порядковый номер) группы (счетчик начинается, например, с 1)

  • , если 1-й столбец = 0и 2-й столбец = 0, а следующая строка пуста. Таким образом, желаемый результат в соответствии с приведенным выше примером будет

    1
    5
    6

  • , если первый столбец = 0, а второй столбец может меняться, а следующая строка пуста. Таким образом, желаемый результат в соответствии с приведенным выше примером будет

    3

  • ... и т. Д. Как это можно обобщить таким образом, чтобы мы могли установить в начале, какой случай мы хотели бы получить?Может быть много случаев в зависимости от значений столбцов в группе.

Мы можем представить это, если подумать о чем-то вроде этого: первый столбец означает количество домов на улице, а второй столбец - количество комнат в доме.Теперь я хотел бы найти все возможные виды улиц в городе, что означает, например,

давайте выберем те улицы, в которых есть два дома с разным количеством комнат, в первом доме есть3 комнаты, а во втором доме 2 комнаты.Таким образом, у нас есть get get 2, потому что это требование удовлетворяет этой группе в файле

0 0
0 1
0 2
1 0
1 1

Важно: 0 0 означает, что есть один дом с одной комнатой

Исправление : если в доме только один дом, то в нем всего одна комната!Как и в случаях Группа 1, Группа 5 и Группа 6. Помните, что во втором столбце указан номер комнаты, а 0 означает «1 комната», 1 означает «2 комнаты» и т. Д.Это просто счетчик, который начинается с 0, а не с 1, извините, если он немного сбивает с толку ...

Ответы [ 3 ]

3 голосов
/ 07 января 2012

Я не знаю, каков будет ваш ожидаемый результат, однако я преобразовал / расшифровал ваш числовой шаблон в значимый формат группы / дома / комнаты.любой дальнейший «запрос» может быть выполнен для этого содержимого.

см. ниже:

kent$  cat file
0 0

0 0
0 1
0 2
1 0
1 1

0 0
0 1
0 2

0 0
1 0
2 0
3 0

0 0

0 0

awk:

kent$  awk 'BEGIN{RS=""} 
        { print "\ngroup "++g; 
        delete a;
        for(i=1;i<=NF;i++) if(i%2) a[$i]++;
        for(x in a) printf "House#: %s , Room(s): %s \n", x, a[x]; }' file

мы получаем вывод:

group 1
House#: 0 , Room(s): 1 

group 2
House#: 0 , Room(s): 3 
House#: 1 , Room(s): 2 

group 3
House#: 0 , Room(s): 3 

group 4
House#: 0 , Room(s): 1 
House#: 1 , Room(s): 1 
House#: 2 , Room(s): 1 
House#: 3 , Room(s): 1 

group 5
House#: 0 , Room(s): 1 

group 6
House#: 0 , Room(s): 1 

обратите внимание , что сгенерированный формат можно изменить в соответствии с вашим "фильтром" или "запросом"

ОБНОВЛЕНИЕ

Комментарий ОП:

Мне нужно знать номер группы (групп), которые имеют / имеют, например, 1 дом с одной комнатой.Вывод будет в вышеприведенном случае: 1, 5, 6

, как я уже сказал, основываясь на ваших критериях запроса, мы могли бы настроить вывод awk для следующего шага.теперь я изменяю awk выше:

awk 'BEGIN{RS=""} 
        {print "";  gid=++g; 
        delete a;
        for(i=1;i<=NF;i++) if(i%2) a[$i]++;
        for(x in a) printf "%s %s %s\n", gid,x, a[x]; }' file

это будет выводить:

1 0 1

2 0 3
2 1 2

3 0 3

4 0 1
4 1 1
4 2 1
4 3 1

5 0 1

6 0 1

формат g roupIdx houseIdx numberOfRooms и между группами есть пустая строка.мы сохраняем текст выше в файл с именем decoded.txt

, чтобы ваш запрос мог быть выполнен по этому тексту:

kent$  awk 'BEGIN{RS="\n\n"}{if (NF==3 && $3==1)print $1}' decoded.txt
1
5
6

последняя строка awk выше означает,выведите номер группы, если номер комнаты ($ 3) = 1 и в группе есть только одна строка.

2 голосов
/ 07 января 2012

Perl решение.Он преобразует входные данные в этот формат:

1|0
2|1 2
3|2
4|0 0 0 0
5|0
6|0

Первый столбец - номер группы, во втором столбце - количество комнат (минус один) всех отсортированных домов.Для поиска группы с двумя разными домами с 2 и 3 комнатами вы можете просто grep '|1 2$', для поиска групп только с одним домом с одной комнатой, grep '|0$'

#!/usr/bin/perl
#-*- cperl -*-

#use Data::Dumper;

use warnings;
use strict;

sub report {
    print join ' ', sort {$a <=> $b} @_;
    print "\n";
}

my $group = 1;
my @last = (0);
print '1|';
my @houses = ();
while (<>) {
    if (/^$/) { # group end
        report(@houses, $last[1]);
        undef @houses;
        print ++$group, '|';
        @last = (0);
    } else {
        my @tuple = split;
        if ($tuple[0] != $last[0]) { # new house
            push @houses, $last[1];
        }
        @last = @tuple;
    }
}

report(@houses, $last[1]);

Он основан наДело в том, что для каждого дома важна только последняя строка.

2 голосов
/ 07 января 2012

Сначала я определю класс Дома и класс Группы:

class House:
    def __init__(self, rooms):
        self.rooms = rooms


class Group:
    def __init__(self, index, houses):
        self.index = index
        # houses.values() is a list with number of rooms for each house.
        self.houses = [House(houses[house_nr]) for house_nr in sorted(houses)]

    def __str__(self):
        return 'Group {}'.format(self.index)

    def __repr__(self):
        return 'Group {}'.format(self.index)

Затем проанализируем данные в эту иерархическую структуру:

with open('in.txt') as f:             
    groups = []

    # Variable to accumulate current group.
    group = collections.defaultdict(int)

    i = 1
    for line in f:
        if not line.strip():
            # Empty line found, create a new group.
            groups.append(Group(i, group))
            # Reset accumulator.
            group = collections.defaultdict(int)
            i += 1
            continue

        house_nr, room_nr = line.split()
        group[house_nr] += 1
    # Create the last group at EOF
    groups.append(Group(i, group))

Затем вы можете делать такие вещи:

found = filter(
    lambda g:
        len(g.houses) == 1 and # Group contains one house
        g.houses[0].rooms == 1, # First house contains one room
    groups)
print(list(found)) # Prints [Group 1, Group 5, Group 6]

found = filter(
    lambda g:
        len(g.houses) == 2 and # Group contains two houses
        g.houses[0].rooms == 3 and # First house contains three rooms
        g.houses[1].rooms == 2, # Second house contains two rooms
    groups)
print(list(found)) # Prints [Group 2]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...