Содержание сайта
Главная Новичку Цитаты Реализации Статьи Документация
Компании Программы Ссылки Обсуждение Обсуждение 2 Гостевая

Тестовая задача "Обработка записей из файла"

Условие

Нарисовать блок-схему, реализующую следующий алгоритм:

Дан входной файл INF с последовательным доступом (допускаются операции открытия и закрытия файла, проверка на конец файла, чтение текущей записи и перехода к следующей записи). Файл содержит записи одинаковой структуры, отсортированные в порядке возрастания значений целочисленного ключевого поля, содержащегося в записях. В файле INF могут находиться записи с одинаковыми значениями ключа. Требуется создать выходной файл OUTF, который формируется из входного файла INF по следующим правилам:

Если для некоторого значения ключа запись с этим значением ключевого поля отсутствует в INF, то такой записи не должно быть и в файле OUTF. Если для некоторого значения ключа в файле INF присутствует только одна запись с таким значением ключевого поля, то эта запись должна быть скопирована в файл OUTF.
Если для некоторого значения ключа в файле INF присутствует некоторое нечетное количество записей с таким значением ключевого поля, то в файл OUTF должна быть скопирована та запись из этого множества, которая физически расположена в файле INF первой среди всех записей с данным значением ключа.
Если для некоторого значения ключа в файле INF присутствует некоторое четное количество записей с таким значением ключевого поля, то в файл OUTF должна быть скопирована та запись из этого множества, которая физически расположена в файле INF последней среди всех записей с данным значением ключа.

Например:

INF: k2, k3, k4a, k4b, k4c, k8, k99a, k99b, k100a, k100b, k100c, k100d
OUTF: k2, k3, k4a, k8, k99b, k100d.

Решение

Т.к. из условия неясно как именно записанны данные в файле (разделители, чем представляются пустые значения) я пропущу чтение и запись из файла. Тогда на вход нашего алгоритма вместо файла мы подадим коллекцию. Результатом то-же будет являться коллекция.

Вход: 2->nil 3->nil 4->'a' 4->'b' 4->'c' 8->nil 99->'a' 99->'b' 100->'a' 100->'b' 100->'c' 100->'d'.
Результат: 2->nil 3->nil 4->'a' 8->nil 99->'b' 100->'d'.

(input := OrderedCollection new)
     add: 2->nil;
     add: 3->nil;
     add: 4->'a';
     add: 4->'b';
     add: 4->'c';
     add: 8->nil;
     add: 99->'a';
     add: 99->'b';
     add: 100->'a';
     add: 100->'b';
     add: 100->'c';
     add: 100->'d'.

Собственно решение на Smalltalk-е:

(input groupedBy: [:each | each key] ) collect:
	 [:each | each size even
		    ifTrue: [each last]
		    ifFalse: [each first] ]

Вот как это работает:
input - это наш вход.
input groupedBy: [:each | each key] - операция аналогичная group by в SQL, условием группировки является ключевое поле.
Вот что в нашем случае вернет groupedBy:

2 -> #(2->nil)
3 -> #(3->nil)
4 -> #(4->a 4->b 4->c)
8 -> #(8 -> nil)
99 -> #(99->a 99->b)
100 -> #(100->a 100->b 100->c 100->d)
(each size \\ 2 = 0)
      ifTrue: [each last]
      ifFalse: [each first]

Если коллекция содержит кратное двум к-во элементов - возвращается последний элемент, иначе первый. Например для #(100->a 100->b 100->c 100->d) вернется последний элемент, т.е. 100->d
А для (4->a 4->b 4->c) вернется первый элемент, т.е. 4->a.

Alex Baran




Есть комментарии? Пишите.