powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Группировка (не простая)
25 сообщений из 33, страница 1 из 2
Группировка (не простая)
    #37464184
_cK_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Помогите решить следующую задачку.

Есть таблица с переменными, обладающими некоторыми параметрами.
Есть таблица с некоторыми условиями (группы). Все переменные так или иначе удовлетворяют одному из условий, и одна переменная никогда не попадет в две группы.

Теперь собственно задача. На группы наложено ограничение в минимум N переменных, попадающих в данную группу. Если в группу попадает менее N переменных, группы необходимо объединять. Объединять тоже необходимо в определенном порядке. Таблица группы выглядит примерно так:

group lvl1 lvl2 lvl3
a 1 1 1
b 2 1 1
c 3 2 1
d 4 2 1

Это означает, что если количество элементов в 1 или 2 (3 или 4) группе будет недостаточно, то их необходимо объединить в группу 1 (2) на lvl2. А если на lvl2 в 1 или 2 группе будет все еще недостаточно элементов необходимо и их объединить.

Заранее спасибо.
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37464191
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И какое отношение эта задача имеет к FoxPro? Вам, скорее, туда ...
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37464192
_cK_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AndreTM,

Ок. И все это нужно сделать в FoxPro :)

P.S. если все еще не тот раздел, не мог бы модератор перенести в упомянутый выше AndreTM раздел. Спасибо.
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37464193
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нет, ну если это действительно нужно сделать в Фоксе, то тогда с постановке оч-чень мало данных...
У вас что, таблицы переменных и условий никак не связаны (ну, то есть, я так понял, что чисто аналитически, и никаких ключевых полей)?
Что вы подразумеваете под "групировкой"? Вам надо отобрать список групп? Изменить таблицу с группами?
Вообще, неплохо бы привести корректно структуру таблиц... и данные по этим вашим "переменным", поскольку принцип не до конца ясен.
Возможно, у вас вообще схема данных сделана неверно для вашей предметной области.
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37464196
_cK_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AndreTM,

Да, таблица переменных и условий никак не связаны. Да и схемы данных то нет. Дело в том, что данная задача носит чисто оптимизационный характер. Ее результаты нужны для дальнейшей работы. Вручную ее решить достаточно просто, однако возможно процесс необходимо будет повторить несколько раз, поэтому хотелось бы автоматизировать. Выбор FoxPro обусловлен лишь тем, что на работе установлен лишь он, а в теме этой написал из-за синтаксиса foxpro'шного.

Задачу, наверно, проще описать следующим образом:
Есть много-много яблок разного цвета и размера. (переменные)
Есть корзины, в которые необходимо поместить все яблоки. (группы)

То есть задача раскидать все яблоки по корзинам.

На корзины наложено ограничение в минимальное количество яблок. То есть, например, если маленьких зеленых яблок мало - из нужно объединить со средними зелеными яблоками (ну или желтыми маленькими, как угодно :) ).

То есть в лучшем случае мы обходимся без объединений корзин и в каждой из них есть больше необходимого минимума яблок.

В худшем случае все корзины объединяются. Порядок объединений задан. Ну вроде все.
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37464381
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Извините, но если Вы описываете задачу на уровне яблок/корзин, то и ответ получите только на уровне яблок/корзин. Если же Вы желаете получить некий код, то хотя бы приведите пример исходных данных и того, что хотите получить в результате.

Например, каким образом связаны таблицы переменных и групп? Ну, каким образом можно вычислить сколько переменных входят в одну группу? Что Вы понимаете под "объединением"? Если объединяемые группы содержат разные условия, то какие условия должны попасть в итоговую (объединенную) группу?
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37464403
_cK_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ,

Это я конечно неправильно сделал, что выплеснул всю задачу сюда. Наверно, лучше описать имеено проблему.

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

группа, кол-во элементов, этап_объединения_1, этап_объединения_2, этап_объединения_3..
1, 60, 1, 1, 1
2, 70, 2, 1, 1
3, 110, 3, 2, 1
4, 30, 4, 3, 1
5, 150, 5, 3, 1

Мы разложили некоторые переменные по группам. На данном этапе появляется ограничение на количество элементов группы снизу.
Минимальное количество элементов = 100. Также дается порядок объединения групп. Рассмотрим на данном примере, что должно получится:

На входе имеем 5 групп, 2 из содержат более 100 элементов, остальные нет. Смотрим на первый этап объединения, тут объединения нет. Значит задача не решена. Идем на второй уровень, и здесь все получается хорошо: 60+70>100 и 30+150>100.

Таким образом, из 5 изначальных групп, получилось 3. Понятно, что последним этапом объединения групп является объединение всех групп.

На данный момент самым сложным для меня представляется следующее: как проанализировать входящий файл на количество этапов объединения, при условии, что мы знаем принцип, по которому называются поля, например, level1, level2, level3, ... , leveln. Как определить количество названных таким образом столбцов? Количество отличных от level# столбцов переменно.


Но как-то некрасиво не ответить Вам на вопросы, поэтому:
1. каким образом связаны таблицы переменных и групп?
аналитически (на группы наложены условия)
2. ну, каким образом можно вычислить сколько переменных входят в одну группу?
по условию, условия записаны перечислением определенных характеристик, которыми должна обладать переменная, т.е. возвращаясь к яблокам и корзинам, примером условия некоторой корзины может быть: цвет='зеленый' И размер='средний'
3. Что Вы понимаете под "объединением"?
сумма элементов групп
4. Если объединяемые группы содержат разные условия, то какие условия должны попасть в итоговую (объединенную) группу?
новое_условие=(условие1 OR условие2)
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37466070
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_cK_На данный момент самым сложным для меня представляется следующее: как проанализировать входящий файл на количество этапов объединения, при условии, что мы знаем принцип, по которому называются поля, например, level1, level2, level3, ... , leveln. Как определить количество названных таким образом столбцов? Количество отличных от level# столбцов переменно.
Структуру (список полей) таблицы можно получить через AFILEDS() или циклом FIELD()+FCOUNT(). Если в последовательности нумерации полей level# не может быть "дыр", то исходя из того факта, что общее количество полей не может превышать 255 можно "тупо" написать цикл от 1 до 255, и проверять, существует ли поле с таким именем через TYPE("MyTable.MyField") <> "U"

Ну, например, можно действовать так

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
* Курсор (временная таблица) со списком номеров уровней и именем поля уровня
create cursor curLevels (numLevel I, fieldName C( 10 ))

* Вариант  1 
Local lnI, laFields( 1 )
select MyTab
for lnI =  1  to afields(laFields)
    if UPPER(LEFT(laFields[m.lnI,  1 ], 5 )) == "LEVEL"
        insert into curLevel (numLevel, fieldName) values (val(subStr(laFields[m.lnI,  1 ], 6 )), laFields[m.lnI,  1 ])
    endif
endfor

* Вариант  2 
local lnI
select MyTab
for lnI =  1  to FCOUNT()
    if UPPER(LEFT(FIELD(m.lnI), 5 )) == "LEVEL"
        insert into curLevel (numLevel, fieldName) values (val(subStr(FIELD(m.lnI), 6 )), FIELD(m.lnI))
    endif
endfor

* Вариант  3 
local lnI, lcFieldName
select MyTab
for lnI =  1  to  255 
    lcFieldName = "level" + ltrim(str(m.lnI, 3 ))
    if type("MyTab." + m.lcFieldName) <> "U"
        insert into curLevel (numLevel, fieldName) values (m.lnI, m.lcFieldName)
    endif
endfor

Какой вариант больше нравится, решайте сами. Далее остается просто пройтись SCAN по полученной выборке, упорядочив ее по возрастанию номера уровня

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
select curLevels 
index on numLevel tag numLevel
go top

local lcField
SCAN
    lcField = curLevels.fieldName

    select ;
        &lcField as nLevel, ;
        sum(nElements) as sumElements, ;
        count(*) as kol ;
    from MyTab ;
    into cursor curUnion nofilter ;
    group by  1  ;
    having count(*) >  1  and sum(nElements) >  100 

    * Если в курсоре curUnion что-то есть, то это предмет для последующего объединения
    if _TALLY >  0 
        * Здесь выполняем объединение групп, код которых записан в поле nLevel, а имя поля в переменной lcField
    endif

ENDSCAN
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37466495
_cK_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ,

большое спасибо Вам.
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37466614
P0039
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вова ? Не надо грязи в женской бане.
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37470148
_cK_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ,

еще раз спасибо и не могли бы Вы еще помочь мне немного?

Вопрос следующий: как реализовать для этой же задачи группировку на разных уровнях?

В приложенном примере, 9 групп и 3 этапа объединения. Тут правильнее, как мне кажется, пойти сверху вниз, то есть от крупного объединения к мелким. В данном примере (ограничение 100 элементов на группу), на 3ем этапе мы видим 160+250 элементов > 100. Идем дальше, на втором этапе и 160, и 250 больше 100. Идем дальше, 80 элементов в 1ой и второй группе не удовлетворяют условию, поэтому для них оставляем объединение - stage2_group1. Однако, и 150, и 100 >= 100, поэтому группу 2 из stage2 бьем еще раз.

Таким образом получаем объединенные группы:
stage2_group1
stage1_group3
stage1_group4

Заранее спасибо!
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37471348
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не знаю. Как мне кажется, простого алгоритма не будет в любом случае. Например, если Вы пойдете от Stage3, то как Вы определили, что по Stage3 ничего суммировать не надо? Почему сразу перешли к Stage2?

А как быть вот в таком случае

Group Amount Stage1 Stage2 Stage3a 30 1 1 1b 30 1 1 1c 30 2 1 1d 60 3 2 1e 60 3 2 1

"С наскока" тут не получится. Надо "думать, слова подбирать" (с). Так с налета, я даже не скажу, как лучше. Вроде бы, общий алгоритм понятный, но вот его реализация будет относительно сложной.

Если идти от "верхних" уровней к "нижним" (от Stage3 к Stage1), то для суммирования по верхнему уровню необходимо будет предварительно узнать результаты суммирования по нижнему уровню. И при этом учитывать тот факт, что суммирование на верхнем уровне изменяет результаты суммирования на нижних уровнях (часть уровней пропадает). Это больше похоже на итерационные циклы с многократными проходами и пересчетами.

Если идти от "нижних" уровней к "верхним" (от Stage1 к Stage3), то тут возникают другие проблемы. Необходимость учитывать и те суммы, которые, вроде бы, уже как объединены. Например, в приведенном выше примере по Stage1 = 3. Там сумма сразу дает 120 и вроде бы этого достаточно. Но для Stage1=1 - не хватает и поэтому, в результате, он будет объединен и со Stage1=3.

Проблемы есть при обоих способах вычисления. Разные, но есть.
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37472024
_cK_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ,

может я чего-то не предусматриваю, но мне кажется, что алгоритм должен выглядеть так:

*пусть stage1 - самое крупное объединение

для i = 2 до n
суммируем элементы по группам этого уровня, сохраняем в массив;
(для вашего примера это 1-1 с мощностью 90 и 1-2 со 120)

если все элементы массива вида 1-Х содержат >= 100 элементов
(Х зависит от этапа объединения, сейчас Х на втором месте, так как i = 2)

то сохраняем в таблицу (со всеми группами в отдельную колонку - актуальный этап объединения) i для групп вида 1-Х

иначе i -1, и исключаем из дальнейшего рассмотрения
следующий

Как-то так.
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37472457
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, да. Схема примерно такая. Я и говорю, что для определения того, надо ли объединять на верхнем уровне нужен анализ на нижнем уровне. И с "сохранением в таблицу" будут тонкости. Впрочем, это будет ясно на практике. Когда начнете писать код.
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37472497
_cK_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ,

Ну вроде с алгоритмом не было проблемы, хотя я понимаю, что возможны тонкости при реализации.

Но написал я сюда только по одной причине - я не могу перевести алгоритм в код и именно на этом этапе надеялся на помощь..
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37472839
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если время терпит, то попробую на выходных...
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37473509
_cK_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ,

Спасибо, буду очень признателен. Сам тоже попробую, может и выйдет что-нибудь.
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37474752
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, вот, что получилось. Правда, некоторые условия приняты "по умолчанию", чтобы не перегружать код.
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37474879
_cK_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ,

Спасибо большое. По понятным причинам, чтобы разобраться в коде мне нужно больше времени. Однако, мне кажется, что программа работает несколько некорректно. При таких условиях результат должен был быть:
1 гр - 160
2 гр - 150
3 гр - 100
4 гр - 150

Также я "поигрался" с исходными данными и выявил некоторую закономерность - похоже, что на stage1 не происходит разбиения.

Плюс при некоторым вариантах исходных данных возможно задубливание (например, если ввести группам a,b,c,d количество элементов по 20). Собственно поэтому в алгоритме я предлагал результирующая таблицу вида:
a, 40, stage2-1
b, 40, stage2-1
c, 40, stage2-1
d, 40, stage2-1
e, 50, stage1-3
f, 50, stage1-3
g, 50, stage1-3
h, 50, stage1-4
i, 50, stage1-4
j, 150, stage1-5

[имя_группы], [мощность], [уровень_объединения], [номер_объединенной_группы].

То есть обновляемая последняя колонка. Такой вид результата легко поддается анализу.

Если у Вас будет время/возможность/желание помочь я буду очень рад. Еще раз спасибо.
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37475238
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да. Было несколько ошибок. Во вложении исправленный вариант

Насчет идентификации, Вы забываете тот факт, что необходимо знать ВСЕ значения до глубины объединения. Например, для объединения групп e+f+g необходимо указать 3 кода всех трех уровней. Т.е. stage1=3 + stage2=2 + stage1=1. Пропустить, например, второй уровень - невозможно! Теряется однозначность идентификации, ведь это может окзаться и, например, stage2=1

Другими словами, идентификация в данной задаче вещь переменная. Зависит от глубины объединения. Для объединения на уровне stage1 необходимо знать 3 кода, для объединения на уровне stage2 - 2 кода, а для объединения на уровне stage1 - 1 код

Собственно, вокруг этого и крутится алгоритм. Постепенное наращивания количества идентификаторов. На каждом следующем шаге добавляется по одному идентификатору. Плюс на последнем шаге чуть другой алгоритм, поскольку он анализирует не следующий уровень, а текущий (последний)
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37475881
_cK_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ,

все равно не проходит проверку - поставить всем группам по 10 элементов, результатом должна быть одна группа :(.
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37476064
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я же говорю, что алгоритм будет не очень-то простой В смысле, все возможные варианты сразу не предусмотришь. Ну, держите следующий вариант
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37476109
_cK_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ,

похоже сработало, пока не уверен на 100%, но кажется есть.

Подскажите, пожалуйста, как проанализировать результат, я имею ввиду, что при таких условиях:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Insert into curData (groupName, amount, stage1, stage2, stage3) values ('a',  50 ,  1 ,  1 ,  1 )
Insert into curData (groupName, amount, stage1, stage2, stage3) values ('b',  50 ,  1 ,  1 ,  1 )
Insert into curData (groupName, amount, stage1, stage2, stage3) values ('c',  50 ,  2 ,  1 ,  1 )
Insert into curData (groupName, amount, stage1, stage2, stage3) values ('d',  50 ,  2 ,  1 ,  1 )
Insert into curData (groupName, amount, stage1, stage2, stage3) values ('e',  30 ,  3 ,  2 ,  1 )
Insert into curData (groupName, amount, stage1, stage2, stage3) values ('f',  20 ,  3 ,  2 ,  1 )
Insert into curData (groupName, amount, stage1, stage2, stage3) values ('g',  30 ,  3 ,  2 ,  1 )
Insert into curData (groupName, amount, stage1, stage2, stage3) values ('h',  20 ,  4 ,  2 ,  1 )
Insert into curData (groupName, amount, stage1, stage2, stage3) values ('i',  40 ,  4 ,  2 ,  1 )
insert into curData (groupName, amount, stage1, stage2, stage3) values ('j',  50 ,  5 ,  3 ,  1 )
insert into curData (groupName, amount, stage1, stage2, stage3) values ('k',  50 ,  5 ,  3 ,  1 )

Результат будет:
Код: plaintext
1.
2.
3.
4.
groupName, amount, stage1, stage2, stage3
e,          140 ,     3 ,       2 ,       1 
a,          100 ,     1 ,       1 ,       1 
c,          100 ,     2 ,       1 ,       1 
i,          100 ,     5 ,       3 ,       1 

То есть я вижу, как это получилось, но можно ли как-нибудь поставить в соответствие имя новой группы к старым?
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37476124
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А как Вы себе это представляете? В смысле, в каком виде Вы хотите видеть эти соответствия? На всякий случай, дополнительный вопрос: значение поля GroupName - уникально или может повторяться? Т.е. встает вопрос идентификатора соответствия.

И еще, я формировал значения "суммирующихся" полей как минимальное из группы. Но ведь, например, значение поля Stage по которому нет группировки можно записать как 0 (не существующее значение). Тоже будет своеобразным признаком.
...
Рейтинг: 0 / 0
Группировка (не простая)
    #37476152
_cK_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ,

Сегодня я получил input, раньше не было возможности выложить. Посмотрите, пожалуйста:
В приложенном файле:
1. знакомые поля stage1-stage6
2. order - номер группы
3. также было поле "условие", я его удалил, чтобы не загромождать таблицу + это не важно, так как из этих условий я получаю количество элементов (мощность) - колонки m_hor, obk, okt и т.д. Они создаются в цикле.
4. Также в цикле я создаю для каждой колонки с количеством элементов, колонку с таким же названием + первая буква 's'.
5. И вот в эти колонки пытаюсь проставить этап объединения (пытаюсь, потому что у меня все не выходит).

Возвращаясь к вопросу об имени группы - главное, чтобы каждому order (самой мелкой группе) соответствовала объединенная группа, то есть те группы, которые были объединены друг с другом, будут иметь одинаковое название объединенной группы.

На предыдущем примере, если оставить имена начальных и итоговых групп, то следующий вид был бы идеален:
Код: plaintext
1.
2.
3.
4.
groupName, amount, stage1, stage2, stage3
e,          140 ,     3 ,       2 ,       1 
a,          100 ,     1 ,       1 ,       1 
c,          100 ,     2 ,       1 ,       1 
i,          100 ,     5 ,       3 ,       1 



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
объединенная_группа, изначальная_группа
e,              e
e,              f
e,              g
e,              h
e,              i
a,              a
a,              b
c,              c
c,              d
i,              j
i,              k
...
Рейтинг: 0 / 0
25 сообщений из 33, страница 1 из 2
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Группировка (не простая)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]