Я отвечаю за переписывание старого кода VB. Я понимаю, как это работает, но я чувствую, что есть гораздо более эффективный способ сделать то, что они сделали. Я просто не могу понять, что это такое. Вот надуманный пример, который с точки зрения требований к данным действительно похож на то, что мне нужно сделать.
Пользователь должен выбрать производителя, марку, модель и цвет своего автомобиля в графическом интерфейсе. У меня большой текстовый файл, который выглядит примерно так:
Ford Truck F150 red
Ford Truck F150 blue
Ford Truck F150 black
Ford Truck F150 silver
Ford Truck F250 red
Ford Truck F250 green
Ford Sedan Taurus red
Ford Sedan Taurus green
Ford Sedan Taurus white
Ford...
...
Subaru SUV Forester blue
Subaru SUV Forester red
Subaru SUV Outback Black
Subaru SUV Outback Green
Subaru SUV Outback Blue
Subaru SUV Outback Red
Subaru...
...
etc.
Таким образом, если первый выбор - Subaru, во втором поле (make) не должно быть возможности выбрать Truck, поскольку ни один из Subarus не является грузовиком. Точно так же, если они выбирают Ford, Sedan и Taurus, то в последнем поле (цвет) не должна отображаться опция для выбора синего цвета. Или черный. Или что-нибудь кроме красного, зеленого или белого.
Люди, которые написали код до меня, придумали это (в python-y psuedocode):
def getValidOptions():
items = []
for i from 0 to numRows:
options = getLine().split()
if selectingManufacturer:
if options[0] not in items:
items.append(options[0])
else if selectingMake:
if selectedManufacturer == options[0] and options[1] not in items:
items.append(options[1])
else if selectingModel:
if selectedManufacturer == options[0] and selectedMake == options[1] and options[2] not in items:
items.append(options[2])
else if selectingColor:
if selectedManufacturer == options[0] and selectedMake == options[1] and selectedModel == options[2] and options[3] not in items:
items.append(options[3])
return items
Я думаю, что это просто отвратительно, как на уровне алгоритма, так и на уровне синтаксиса. С одной стороны, он анализирует весь файл, когда ему нужно только прочитать пару строк, если все сделано правильно. Чтобы сделать это еще более неэффективным, мои реальные данные имеют 6 вариантов выбора, а не только 4. Это также хранит больше данных, чем необходимо, учитывая количество дублирующихся данных.
Я ищу другой способ хранения данных в файле или другой способ их анализа, чтобы сделать getValidOptions
функцию более привлекательной и эффективной. Есть ли способы, которыми я мог бы сделать это?
Ответы:
Все остальные ответы, которые я читаю, похоже, игнорируют два основных правила разработки программного обеспечения:
сначала уточнить требования (особенно требования к производительности и хранению)
Сохраняй это простым, глупым (см. ПОЦЕЛУЙ )
Вы написали «текстовый файл большой», но не написали слишком большой, поэтому я предполагаю, что на самом деле в его размере нет ничего плохого, кроме вашего интуиции. Поэтому, если загрузка файла на самом деле не занимает много времени, и ваш ИТ-отдел или кто-то другой не жалуется на неиспользуемое дисковое пространство, и никто не жалуется на проблемы с сохранением файла, пусть формат файла такой, какой он есть - не стоит недооценивать ценность простоты.
Вы также жалуетесь на эффективность алгоритма, который на самом деле не так эффективен, как мог бы быть, но у него есть одно очень большое преимущество: он просто умопомрачительный и работает. Поэтому, пока он достаточно эффективен, не применяйте преждевременную оптимизацию.
Итак, давайте предположим, что программа работает достаточно быстро. Сначала вы должны спросить, как можно улучшить код с точки зрения простоты и принципа СУХОЙ? И это действительно то, что нужно улучшить, поскольку текущий код не СУХОЙ. В вашем примере, в четыре раза появляется почти одинаковое тестирование блока кода, если параметры на «верхних уровнях» соответствуют текущей строке, что приводит к четырехкратному вызову «добавления» того же типа (в вашем реальном коде повторение происходит). как минимум шесть раз, как вы написали). Вы можете легко избежать этого, вводя числовой уровень выбора или передавая уже выбранные параметры в упорядоченном списке. Используя ваш псевдокод, это приводит к чему-то вроде
Так что это по сути тот же алгоритм без повторяющегося кода.
Поскольку очевидно,
getValidOptions
что его нужно вызывать более одного раза (хотя бы один раз на уровень), я предлагаю применить только одну оптимизацию (если это не так): убедитесь, чтоgetLine
функция извлекает свои данные из основной памяти, и не читать файл с диска снова и снова.источник
Итак, ваши данные имеют древовидную структуру, где для каждого производителя у вас есть дерево моделей, а для каждой модели у вас есть цвет (и т. Д.).
Таким образом, вы можете разделить процесс этих данных в два этапа:
Древовидная структура может быть реализована с помощью так называемого хеша , ассоциативного массива или словаря в таких языках, как Java, PHP, Javascript или Python. С этой структурой у вас есть:
В зависимости от вашего языка программирования это может быть реализовано быстрее или медленнее. Например:
Runtime.Serialization.Formatters.Binary.BinaryFormatter
может пригодиться что-то подобное , но я не специалист по сериализации с VB.Net.Class
интерфейс, реализующий интерфейсjava.io.Serializable
.Рекомендации :
1: https://dvanderboom.wordpress.com/2008/03/15/treet-implementing-a-non-binary-tree-in-c/
- Полное объяснение реализации дерева в C #.
- Ищите комментарий, где кто-то спрашивает о сериализации этого объекта, и ответ на этот комментарий.
источник
tree with an arbitrary number of nodes
реализацией.Один из простых способов хранения данных - просто поместить их в базу данных SQLite. SQLite, в отличие от большинства баз данных SQL, хорошо подходит для использования в качестве формата файла приложения. Этот подход имеет несколько преимуществ:
select distinct model where manufacturer='ford' and color = 'red'
).Это заставляет вас изучать SQL, но избавляет от необходимости изучать пользовательский формат файла.
источник
Я предполагаю, что вы можете получить произвольный доступ к строкам в файле и, таким образом, можете рассматривать файл как массив записей. Если вы не можете получить произвольный доступ к линиям, то ваш алгоритм - лучший из возможных.
Для более быстрого доступа храните данные в 6 файлах, где каждый файл является указателем на следующий.
Существует множество способов создания индексов плоских файлов. Я обычно использую диапазон индекса. Когда пользователь делает каждый выбор, используйте диапазон, чтобы ограничить чтение следующего файла.
Вот как я бы создал индексы для предоставленных вами образцов данных.
Конечно файл должен быть отсортирован. Я пронумеровал линии для иллюстрации; номера строк не должны появляться в файле.
Чтобы создать первый индекс, сделайте запись для каждой уникальной комбинации первых трех полей в файле. В каждой записи сохраните номера первой и последней строки, в которых появляется эта комбинация.
Второй индекс строится аналогично, используя первые два поля первого индекса.
И третий, верхний уровень в данном случае, индекс.
Я думаю, что я переобъясняю концепцию, но в целом вы создаете индекс, удаляя последнее поле и удаляя дубликаты записей.
Вы можете еще больше сократить требования к хранилищу файлов, исключив некоторые избыточные данные.
Например, «первый» индекс в каждой индексной записи всегда на единицу больше, чем «последний» индекс предыдущей записи, или ноль, если предыдущей записи нет. Таким образом, вам не нужно хранить «первые» подписки. Я оставляю их на месте ниже для иллюстрации.
Кроме того, поскольку вы будете использовать только последнее поле в каждой записи для заполнения списка выбора, вам не нужно сохранять другие поля.
Минимальное воспроизведение каскада индексов в конечном итоге выглядит следующим образом, где отметка 'указывает число, которое на самом деле не хранится в файле.
Когда вы заполняете список выбора из индекса, вы используете «первый» и «последний» индексы из выбора пользователя в предыдущем индексе, чтобы ограничить количество прочитанных строк.
Пример:
Вы заполняете первый список выбора из всех
file0.dat
. (Форд, Субару)Пользователь выбирает «Форд». Соответствующие индексы 0 и 1.
Вы заполняете второй список выбора из строк с 0 по 1 из
file1.dat
. (Грузовик, Седан)Пользователь выбирает «Седан». Соответствующие подписки 2 и 2.
Как вы можете видеть, к тому времени, когда пользователь выбрал, например, «Форд», «Седан», «Телец», вы обнаружите, что вам нужны строки только для чтения с 6 по 8,
file3.dat
чтобы заполнить четвертый список выбора.Я прошу прощения за довольно длинное описание, но здесь очень поздно, и у меня нет времени, чтобы написать короткое.
ДОБАВЛЕНО: Если подумать, файлы могут быть объединены в один.
Это используется точно так же, как версия с несколькими файлами, за исключением того, что в первой строке необходимо указать первый диапазон индекса.
источник