Название: Простой (?) поиск Отправлено: Igors от Сентябрь 16, 2018, 11:34 Добрый день
Есть контейнер объектов, каждый имеет такие (интересующие нас) поля. все они НЕ уникальны - имя (QString) - тип (enum или int) - visibility (bool) Нужно: для заданного имени + типа найти "наилучший" объект в контейнере, т.е. - имя должно точно совпадать, иначе объект не найден - тип: если совпадает с заданным - хорошо, это "наилучший", иначе годится любой - visibility: если true это "наилучший", иначе годится и false И наконец если все ключи совпадают, должен быть найден первый (по порядку в исходном контейнеру). Как лучше/техничнее сделать такой поиск ? Спасибо Название: Re: Простой (?) поиск Отправлено: deMax от Сентябрь 18, 2018, 17:18 Обьектов много? Имен не уникальных много? Если в лоб, находим первый объект с именем(если все совпало - в ответ), иначе ищем следующий (если лучше - заменяемб совпало в ответ)... и так пока все объекты не пройдем.
Чтобы быстрее искалось - QMap, QMsql.... Если объектов с одинаковым именем очень много, тогда БД - ищем полное совпадение, потом хуже и хуже... Название: Re: Простой (?) поиск Отправлено: RedDog от Сентябрь 18, 2018, 19:04 QMultiMap можно заюзать, если есть совпадающие имена. Тогда в значениях ее можно хранить структуру int/bool.
Название: Re: Простой (?) поиск Отправлено: Igors от Сентябрь 19, 2018, 08:08 Обьектов много? Причем тут много-мало? :) Интересует корректное, "академическое" решение задачи, действительно ли оно такое уж сложное? А может оно проще "прямого перебора" который кстати здесь достаточно хлопотливый ?... Если объектов с одинаковым именем очень много... Чтобы быстрее искалось - QMap, QMultiMap можно заюзать, если есть совпадающие имена. Тогда в значениях ее можно хранить структуру int/bool. Да, можем создавать любые контейнеры (поиск нужен многократно). И что? Как искать-то? Вначале я подумал слить все проверки в ключ (или оператор <) и отсортировать по этому (композитному) ключу. Тогда поиск: lower_bound и проверяем найденный + предыдуший. Но почему-то мне показалось это не проходит... Или я неправ? Название: Re: Простой (?) поиск Отправлено: Figaro от Сентябрь 19, 2018, 14:09 QMultiMap можно заюзать, если есть совпадающие имена. Тогда в значениях ее можно хранить структуру int/bool. Согласен с QMultiMap, только в значениях проще хранить QVariant… Это мне кажется проще :) Название: Re: Простой (?) поиск Отправлено: RedDog от Сентябрь 19, 2018, 19:02 Обьектов много? Причем тут много-мало? :) Интересует корректное, "академическое" решение задачи, действительно ли оно такое уж сложное? А может оно проще "прямого перебора" который кстати здесь достаточно хлопотливый ?... Если объектов с одинаковым именем очень много... Чтобы быстрее искалось - QMap, QMultiMap можно заюзать, если есть совпадающие имена. Тогда в значениях ее можно хранить структуру int/bool. Да, можем создавать любые контейнеры (поиск нужен многократно). И что? Как искать-то? Вначале я подумал слить все проверки в ключ (или оператор <) и отсортировать по этому (композитному) ключу. Тогда поиск: lower_bound и проверяем найденный + предыдуший. Но почему-то мне показалось это не проходит... Или я неправ? - имя - видимость - тип т.о. у мапы ключ - имя, в значениях отсортированный лист структур, оператор < можно сделать только по полю "видимость". Ну а далее либо самый первый в листе берем, либо есть видимость в фолсе, тогда переходим к следующему. Название: Re: Простой (?) поиск Отправлено: Igors от Сентябрь 20, 2018, 08:27 Исходя из первого поста если я правильно понял, то иерархию поиска можно описать по убыванию: Нет, см первый пост: имя + тип + видимость- имя - видимость - тип т.о. у мапы ключ - имя, Чего это ??? Почему неКод
Название: Re: Простой (?) поиск Отправлено: RedDog от Сентябрь 20, 2018, 09:36 Я может не сильно до конца задачу понял, но показалось, что первичное условие это имя, и если его нет, то далее искать бессмысленно.
Поэтому поиск по оставшимся 2 параметрам можно сократить, объединив элементы с одинаковыми именами. Название: Re: Простой (?) поиск Отправлено: deMax от Сентябрь 20, 2018, 09:47 Причем тут много-мало? :) Интересует корректное, "академическое" решение задачи, действительно ли оно такое уж сложное? А может оно проще "прямого перебора" который кстати здесь достаточно хлопотливый ? А что сложного в прямом переборе? Создаете пустой указатель и перебираете массив, заменяя значение более выгодным (если все совпало, поиск останавливаете).Если память не так важна, и вызовов очень много, то загоните в QMap<QString /*Name*/, QMap<int /*Type*/, bool /*Visible*/>> и двумя строчками извлеките ответ. Название: Re: Простой (?) поиск Отправлено: Igors от Сентябрь 20, 2018, 09:58 Я может не сильно до конца задачу понял, но показалось, что первичное условие это имя, и если его нет, то далее искать бессмысленно. Да, так и есть, правильно понялиПоэтому поиск по оставшимся 2 параметрам можно сократить, объединив элементы с одинаковыми именами. ??? Совершенно непонятный вывод. А остальные правила (или критерии) поиска разве нельзя задать в ключах мапы?А что сложного в прямом переборе? Ну вообще-то прямой перебор - "визитная карточка лоха" :)Если память не так важна, и вызовов очень много, то загоните в QMap<QString /*Name*/, QMap<int /*Type*/, bool /*Visible*/>> и двумя строчками извлеките ответ. Какой Вы быстрый :) Ну во-первых мапа не гарантирует что эл-ты с одним ключом будут в порядке исходного массива. И хотелось бы увидеть эти "две строчки извлечения" :)Название: Re: Простой (?) поиск Отправлено: RedDog от Сентябрь 20, 2018, 13:16 есть мысль построить индексы по каждому полю, в значениях хранить лист индексов элементов в исходном массиве.
тогда при поиске делать пересечение всех трёх индексов. С телефона код не напишу, могу вечером набросать. Название: Re: Простой (?) поиск Отправлено: Igors от Сентябрь 20, 2018, 17:08 есть мысль построить индексы по каждому полю, в значениях хранить лист индексов элементов в исходном массиве. Спасибо, но давайте лучше уясним что писать-то, тогда собсно написание не проблема. Пусть напр ключи в мапе легли тактогда при поиске делать пересечение всех трёх индексов. С телефона код не напишу, могу вечером набросать. Цитировать { "Name", 1, false, 100 } // имя, тип, видимость, индекс в исходном Ищем { "Name", 2, false, 0 }. QMap::lowerBound (std::lowerBound) вернет итератор на второй { "Name", 3, false, 10 }, он "не меньше". Проверяем найденный и предыдущий - у обоих тип не совпадает, у обоих видимость false. Однако был ключ "лучше" - у последнего тоже тип не совпадает, зато видимость true. Поэтому я и решил что не проходит, нужно топать по всем эл-там пока искомое имя не кончится и руками искать "лучший". Верно ли я мыслюсь? { "Name", 3, false, 10 } { "Name", 4, true, 101 } Название: Re: Простой (?) поиск Отправлено: RedDog от Сентябрь 20, 2018, 19:32 вот чего накидал:
Код: #include <QHash> Название: Re: Простой (?) поиск Отправлено: Igors от Сентябрь 21, 2018, 09:12 вот чего накидал: Ну все-таки надо думать о производительности и расходе ресурсов (хотя бы иногда :)). Создавать многочисленные контейнеры на каждом поиске - ну это уж слишкомНазвание: Re: Простой (?) поиск Отправлено: RedDog от Сентябрь 21, 2018, 09:44 вот чего накидал: Ну все-таки надо думать о производительности и расходе ресурсов (хотя бы иногда :)). Создавать многочисленные контейнеры на каждом поиске - ну это уж слишкомЧто касается производительности, то поиск по хешу О(1) в среднем. Пересечение только замедлить может. Ну в общем, принцип пересечения подмножеств я предложил, дальше вам решать, подойдёт ли он под конкретную задачу. ps: у меня в проекте с 300-2000 тыс объектов подобные индексации используются, производительности хватает, памяти на индексирование до 200мб жрется. Название: Re: Простой (?) поиск Отправлено: Igors от Сентябрь 21, 2018, 09:56 Если объектов десятки-сотни миллионов, тогда ... Ну вот, опять пошли "анализы" :) А можно просто "решить задачу" без всяких "если"? Неужели она и вправду настолько сложна, что надо ловчить, привлекать БД и.т.п ? Не аерю. По меньшей мере один вариант есть - в мапе пройтись по всем объектам с одинаковым именем (кода не больше)Название: Re: Простой (?) поиск Отправлено: RedDog от Сентябрь 21, 2018, 10:11 По меньшей мере один вариант есть - в мапе пройтись по всем объектам с одинаковым именем (кода не больше) И смысл мапы при условии, что у всех объектов будет одинаковое имя?ps: это частный случай, того что я написал. Название: Re: Простой (?) поиск Отправлено: ViTech от Сентябрь 21, 2018, 11:52 Ну вот, опять пошли "анализы" :) А можно просто "решить задачу" без всяких "если"? Неужели она и вправду настолько сложна, что надо ловчить, привлекать БД и.т.п ? Не аерю. По меньшей мере один вариант есть - в мапе пройтись по всем объектам с одинаковым именем (кода не больше) Нельзя :). Т.е. можно, но это решение не будет одинаково эффективным для множества разных "если". Если элементов около сотни. Если элементов сотни миллионов. Если можно/нельзя использовать многопоточность. Если быстродействие важнее расходов по памяти. Если наоборот. Напишите одно решение, которое будет одинаково эффективно работать хотя бы для всех тех "если", которые я перечислил :). Название: Re: Простой (?) поиск Отправлено: SimpleSunny от Сентябрь 21, 2018, 13:29 Так а чем вариант с QMap <QMap... не подошел? Поиск правда не совсем 2мя строками, но...
Код
И заполнять обратным перебором как-то так Код
Название: Re: Простой (?) поиск Отправлено: RedDog от Сентябрь 21, 2018, 13:34 Так а чем вариант с QMap <QMap... не подошел? Не выполнится условие "первый в оригинальном массиве"Название: Re: Простой (?) поиск Отправлено: Racheengel от Сентябрь 21, 2018, 14:24 1. Проиндексировать все объекты по именам:
QMap<QString, QList<int> > где в список для каждого уникального имени заносить порядковый номер объекта в оригинальном массиве. 2. При поиске, если имя в мапе найдено, то взять массив индексов и далее "в лоб" только по нему. Ну а иначе объект не найден. Вроде несложно, не? :) Название: Re: Простой (?) поиск Отправлено: SimpleSunny от Сентябрь 21, 2018, 19:26 Так а чем вариант с QMap <QMap... не подошел? Не выполнится условие "первый в оригинальном массиве"Почему это? Название: Re: Простой (?) поиск Отправлено: RedDog от Сентябрь 21, 2018, 19:56 Почему это? Потому что во второй мапе ключ это тип, а не индекс в оригинальном массивеНазвание: Re: Простой (?) поиск Отправлено: Igors от Сентябрь 22, 2018, 07:37 Напишите одно решение, которое будет одинаково эффективно работать хотя бы для всех тех "если", которые я перечислил :). Да не вопросКод Как это улучшить? И что там за дичь с эл-тами которые сами контейнеры? Может лучше на чистом "С" потренироваться, чтобы контейнерами так не ляпать? Нельзя :). Т.е. можно, но это решение не будет одинаково эффективным для множества разных "если". Если элементов около сотни. Если элементов сотни миллионов. Если можно/нельзя использовать многопоточность. Если быстродействие важнее расходов по памяти. Если наоборот. Ну конечно играть роль "эксперта" приятно :), но в очередной раз замечаю (и/или замечу): углубление в детали проекта часто/обычно работает в минус. Проект живет своей жизнью и выводы могут быстро оказаться устаревшими. Напр пока я помню проект с макс 50К объектами, но в связи с недавним переводом на 64 запросто может быть уже и 200-300К. Также оценить "кратность" непросто даже в среднем проекте. Да, объектов может быть и сотка, но поиск зовется для каждой ячейки в таблице. Только убедиться в этом - неск дней разрывания кода, часто чужого. Так может за это время просто сделать "нормально"? :)Название: Re: Простой (?) поиск Отправлено: SimpleSunny от Сентябрь 22, 2018, 12:11 Почему это? Потому что во второй мапе ключ это тип, а не индекс в оригинальном массивеДля каждой комбинации (имя,тип,видимость) хранится только лучшее соответствие, поэтому все подходит под заданные условия. Название: Re: Простой (?) поиск Отправлено: ViTech от Сентябрь 22, 2018, 13:45 Напишите одно решение, которое будет одинаково эффективно работать хотя бы для всех тех "если", которые я перечислил :). Да не вопросКод
Ещё какой вопрос. Вот сидит пользователь, постоянно изменяет данные в контейнере с парой-тройкой сотен тысяч элементов. Иногда(очень редко) ищет элемент по заданным условиям, смотрит на него, и продолжает дальше изменять данные. В предложенном решении каждый раз формируется дополнительный TFindMap (+ память, + время), хотя в лучшем случае нужный элемент найдётся в исходном контейнере менее чем за один проход, в худшем - один проход и ещё немного по наиболее подходящим элементам. И где в Вашем решении хоть какая-нибудь эффективность? На кой нужен дополнительный TFindMap? Оно не эффективно ни по одному критерию из тех, что я приводил. Это плохое решение, переделывайте :). Название: Re: Простой (?) поиск Отправлено: Igors от Сентябрь 22, 2018, 17:28 [Ещё какой вопрос. Вот сидит пользователь, постоянно изменяет данные в контейнере с парой-тройкой сотен тысяч элементов. Иногда(очень редко) ищет элемент по заданным условиям, смотрит на него, и продолжает дальше изменять данные. Все происходит совсем не так :) Юзер может выбрать любое кол-во объектов и записать их установки в файл, потом этот файл надо как-то загрузить (возможно в совсем др сцене) - вот придумали/установили такие правила загрузки по умолчанию. Кстати "установки" - те самые curve(s) с которыми Вы уже знакомы :)В предложенном решении каждый раз формируется дополнительный TFindMap (+ память, + время), хотя в лучшем случае нужный элемент найдётся в исходном контейнере менее чем за один проход, в худшем - один проход и ещё немного по наиболее подходящим элементам. И где в Вашем решении хоть какая-нибудь эффективность? Отчаянное желание придраться :) На кой нужен дополнительный TFindMap? А это замечание обоснованное, ассоциативный контейнер - удовольствие дорогое. Но при загрузке из файла нужно чтобы объект грузился только 1 раз, т.е. найденный "лучший" надо удалять, вот и взял мапу. Определенная доля "халтуры" здесь есть, признаю - но это ж милые цветочки пор сравнению со структурами что предлагают товарищи :)Оно не эффективно ни по одному критерию из тех, что я приводил. Это плохое решение, переделывайте :). Щас, разбежался :)Название: Re: Простой (?) поиск Отправлено: ViTech от Сентябрь 23, 2018, 10:56 Отчаянное желание придраться :) Хотите сказать, что для моего варианта использования Ваше решение является очень эффективным и я всего лишь придираюсь? :)Все происходит совсем не так :) ... Определенная доля "халтуры" здесь есть, признаю - но это ж милые цветочки пор сравнению со структурами что предлагают товарищи :) А откуда товарищам знать, что всё происходит не так, как я описал, а "совсем не так"? Сколько ещё страниц в теме нужно исписать, чтобы выяснить что и как у Вас происходит? Если Вас, конечно, интересует эффективное решение задачи, а не "универсальное академическое среднее по больнице" :). Название: Re: Простой (?) поиск Отправлено: deMax от Сентябрь 28, 2018, 16:02 Академическое - это БД. Для случая когда непонятен текущий объем и непонятна масштабируемость. Если что, всегда можно перескочить на другую БД. или купить сервера помощнее.
Название: Re: Простой (?) поиск Отправлено: Igors от Сентябрь 29, 2018, 08:44 Академическое - это БД. Ой :) Крайность обратная "прямому перебору".А откуда товарищам знать, что .. Да все товарищи правильно поняли как и положено профессиональным программистам. Если данные "не лезут в память" то описание с этого и начинается. Если я об этом не упомянул - значит этой проблемы нет. Так же и с изменением данных "на лету", это совсем др задача. Стало быть речь идет о самой банальной ситуации - построить структуры для поиска один раз, и затем искать многократно. Ну и чего тратить время и место на совершенно ненужные "выяснения" (хз чего) ?Возвращаясь к теме. Практически пробежка по всем объектам с одинаковым именем вполне устраивает. Если юзер назначил всем одинаковые имена - значит сам "злобный Буратино", пусть страдает. Просто стало интересно как же так - все ключи есть, а быстрого поиска .. строго говоря нет. Приходится или перебирать диапазон или городить ужасные структуры (что еще хуже). Вот если бы тип был bool - тогда получается, а так нет. И похоже это нормально. Еще рассматривал такой вариант: ключи = имя + visible + тип, А на поиске (псевдокод) Код Возможно это точнее, хотя возни побольше Название: Re: Простой (?) поиск Отправлено: ViTech от Сентябрь 30, 2018, 12:38 Да все товарищи правильно поняли как и положено профессиональным программистам. Если данные "не лезут в память" то описание с этого и начинается. Если я об этом не упомянул - значит этой проблемы нет. Так же и с изменением данных "на лету", это совсем др задача. Стало быть речь идет о самой банальной ситуации - построить структуры для поиска один раз, и затем искать многократно. Ну и чего тратить время и место на совершенно ненужные "выяснения" (хз чего) ? Так вот значит какая логика должна быть :). Цитировать Украли у мужика корову. Приходит он домой и говорит сыновьям: - У нас корову украл какой-то мудак. Старший брат: — Если мудак — значит маленький. Средний брат: — Если маленький — значит из Малиновки. Младший Брат: — Если из Малиновки — значит Васька Косой. Все выдвигаются в Малиновку и там прессуют Ваську Косого. Однако Васька корову не отдает. Его ведут к мировому судье. Мировой судья: - Ну… Логика мне ваша непонятна. Вот у меня коробка, что в ней лежит? Старший брат: — Коробка квадратная, значит внутри что-то круглое. Средний: — Если круглое, то оранжевое. Младший: — Если круглое и оранжевое, то апельсин. Судья открывает коробку, а там и правда апельсин. Судья — Ваське Косому: - Косой, отдай корову. Название: Re: Простой (?) поиск Отправлено: NoIdea от Октябрь 12, 2018, 19:23 вот чего накидал: Ну все-таки надо думать о производительности и расходе ресурсов (хотя бы иногда :)). Создавать многочисленные контейнеры на каждом поиске - ну это уж слишкомЧто касается производительности, то поиск по хешу О(1) в среднем. Пересечение только замедлить может. Ну в общем, принцип пересечения подмножеств я предложил, дальше вам решать, подойдёт ли он под конкретную задачу. ps: у меня в проекте с 300-2000 тыс объектов подобные индексации используются, производительности хватает, памяти на индексирование до 200мб жрется. Занятно, интересно сравнить по производительности и ресурсам с БД в памяти: http://doc.qt.io/qt-5/qtsql-cachedtable-example.html Код
Название: Re: Простой (?) поиск Отправлено: RedDog от Октябрь 13, 2018, 09:55 Занятно, интересно сравнить по производительности и ресурсам с БД в памяти: На указанных объёмах данных, примерно монопенисуально, в пределах погрешности измерений, и даже файловый вариант БД приемлемые результаты показывает.http://doc.qt.io/qt-5/qtsql-cachedtable-example.html Код
Оптимизация не идёт уже в ключе выбора хранилища данных, а идёт в ключе минимизации обращения к ним, разбиения на подмассивы (в БД отдельные таблицы), прикручивания различного распараллеливания и пр. Удобство БД в том, что она инкапсулирует много рутинной работы, например то же пересечение множеств в любом виде, делается одной строкой. |