Имя: Пароль:
1C
1С v8
Вывод последней строки в таблице значений с условием
0 Штурман
 
26.08.16
07:58
Есть ТЗ:

Колонка1   Колонка2
Второе   C
Второе   D
Второе   E
Второе   F
Первое   A
Первое   B
Третье   G
Третье   H
Третье   I

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

Второе   F
Первое   B
Третье   I


Код такой примерно:


    тз = Новый ТаблицаЗначений;
    тз.Колонки.Добавить("Колонка1");
    тз.Колонки.Добавить("Колонка2");
    стр = тз.Добавить();
    стр.Колонка1 = "Первое";
    стр.Колонка2 = "A";
    стр = тз.Добавить();
    стр.Колонка1 = "Первое";
    стр.Колонка2 = "B";
    стр = тз.Добавить();
    стр.Колонка1 = "Второе";
    стр.Колонка2 = "C";
    стр = тз.Добавить();
    стр.Колонка1 = "Второе";
    стр.Колонка2 = "D";
    стр = тз.Добавить();
    стр.Колонка1 = "Второе";
    стр.Колонка2 = "E";
    стр = тз.Добавить();
    стр.Колонка1 = "Второе";
    стр.Колонка2 = "F";
    стр = тз.Добавить();
    стр.Колонка1 = "Третье";
    стр.Колонка2 = "G";
    стр = тз.Добавить();
    стр.Колонка1 = "Третье";
    стр.Колонка2 = "H";
    стр = тз.Добавить();
    стр.Колонка1 = "Третье";
    стр.Колонка2 = "I";
    
    тз.Сортировать("Колонка1, Колонка2");
    
    СтаршийИндекс = тз.Количество()-2;
    Для сч=0 по СтаршийИндекс цикл
        если тз[сч].Колонка1 = тз[сч+1].Колонка1 тогда
            /////////////////
        конецесли;
    конеццикла;
    


Подскажите, что написать вместо комментариев?
1 Рэйв
 
26.08.16
08:05
До="!№#";
тз.Сортировать("Колонка1,Колонка2")
Для Каждого Стр Из тз Цикл
  Если ДО<>  "!№#" Стр.Колонка1<>ДО Тогда
     //Добавляем куда надо Стр.колонка1 и Стр.Колонка2
  КонецЕсли;
  До=Стр.Колонка1;
КонецЦикла;

//Добавляем последний раз куда надо Стр.колонка1 и Стр.Колонка2

как то так...
2 Рэйв
 
26.08.16
08:06
Обшибся немного:-) Вернее запомнаем не ДО_Колонка1 и ДоКолонка2
и их добавляем

Я так давным давно итги выводил поэтому запарился по привычке:-)
3 Рэйв
 
26.08.16
08:07
ну вобщем надеюсь смысл понятен:-)
4 Горогуля
 
26.08.16
08:24
группируешь по 1й выясняешь максимум номеров строк, соединяешь с исходной по номеру строки
5 Штурман
 
26.08.16
08:33
(2) не совсем понял, ДО что?
6 Штурман
 
26.08.16
08:33
(4) а если надо не совсем максимум последней колонки, а только последнее значение?
7 Горогуля
 
26.08.16
08:35
(6) вот и бери его из строки с максимальным номером
8 Штурман
 
26.08.16
08:37
(7) так метод Свернуть() только суммы вычисляет, а ты говоришь надо Максимум
Как его вычислить?
9 Горогуля
 
26.08.16
08:41
(8) а соединение тебя не насторожило? я про запрос говорю
10 Штурман
 
26.08.16
08:45
(9) Зачем тз добавлять в запрос, а потом обратно в тз, неужели по-другому нельзя?

Попробовал сделать так:
добавил в ТЗ еще одну колонку с именем "Максимум"

код:

СтаршийИндекс = тз.Количество()-2;
    Для сч=0 по СтаршийИндекс цикл
        если тз[сч].Колонка1 = тз[сч+1].Колонка1 тогда
            тз[сч].Максимум = сч;
        конецесли;
    конеццикла;

Почему-то в результате выполнения у последних строк пропуски " "
11 Mauser
 
26.08.16
08:48
Перебираешь в отсортированной табличке строки. На каждом шаге знаешь две строки - текущую и предыдущую. Если ключ в первой колонке в этих двух строках различен, то в предыдущей строке искомые данные, которые надо слить в результат.
Все.
12 Горогуля
 
26.08.16
08:48
(10) не, ну можно и циклами сэмулировать то же. а зачем?
13 Горогуля
 
26.08.16
08:49
(11) сортировка похерит порядок второй колонки
14 Mauser
 
26.08.16
08:49
Хуже студентов, чессдово.
Особо в пятницу.
15 Mauser
 
26.08.16
08:50
(13) а она там зачем?
16 Штурман
 
26.08.16
08:53
сделал так:

    СтаршийИндекс = тз.Количество()-2;
    Для сч=0 по СтаршийИндекс цикл
        если тз[сч].Колонка1 = тз[сч+1].Колонка1 тогда
            тз[сч].Максимум = сч;
        конецесли;
    конеццикла;
    
    СтаршийИндекс = тз.Колонки.Количество() - 1;
    Индекс = тз.Количество() - 1;
    Пока Индекс >= 0 Цикл
        Для Сч = 0 По СтаршийИндекс Цикл
            Если ТипЗнч(тз[Индекс][Сч]) = Тип("Число") Тогда
                тз.Удалить(Индекс);
                Прервать;
            КонецЕсли;
        КонецЦикла;
        Индекс = Индекс - 1;
    КонецЦикла;


как, нормально?
17 Mauser
 
26.08.16
08:53
А чтобы не парится с выходом за границу добавляешь после сортировки в конец барьер - пустую строку
18 Mauser
 
26.08.16
08:54
Потом удаляешь
19 Горогуля
 
26.08.16
08:54
(15) ну ты ж предлагаешь сортирнуть и обходить
20 Горогуля
 
26.08.16
08:55
а у автора критерий последнести - максимальный номер строки
21 Горогуля
 
26.08.16
08:56
(16) нет. ибо тз.Удалить(Индекс). вчитываться не хочу
22 Штурман
 
26.08.16
08:56
(20) да, нужна самая последняя строка с учетов значения первой колонки

код из (16) вроде бы нормально все делает
23 Штурман
 
26.08.16
08:56
(21) так все работает же и выводит то, что я хотел
24 Горогуля
 
26.08.16
08:57
(23) на любых входных данных?
25 Горогуля
 
26.08.16
08:58
пересунь колонку со вторым в конец, а с третьим в начало
26 Горогуля
 
26.08.16
08:58
*строку
27 Штурман
 
26.08.16
08:59
(25) так я же сортировку делаю заранее

тз.Сортировать("Колонка1, Колонка2");
28 Горогуля
 
26.08.16
09:02
тогда слушайся Маузера, если так хочется циклов. а ещё можно сразу получить таблицу нужного вида и не иметь головную мутотень с последующими сортировками и обходами
29 Штурман
 
26.08.16
09:07
(28) меня вообще-то правильный вариант интересует, типа как будет самым верным решением?

В принципе могу ТЗ засунуть в запрос, а там уже отбирать.
Запросом будет правильнее?
30 Горогуля
 
26.08.16
09:08
(29) красивше - однозначно. быстрее - почти наверняка. строк кода меньше - точно нет
31 Garykom
 
гуру
26.08.16
09:09
Вот и выросло поколение 1С-ников которые запросы знают лучше базовых алгоритмов программирования...
32 Штурман
 
26.08.16
09:11
(30) ок, попробую запросом

(31) так в конструкторе запроса кодинг в основном кликами мышки, в то время как алгоритмы надо думать как писать xD
33 Garykom
 
гуру
26.08.16
09:11
(30) Запросом и красивше? Кому как, но тормознее это почти наверняка ибо без группировок не обойтись вместо простого одного цикла.
Сложность выше O(N) как минимум O(2N) будет с запросом.
34 Garykom
 
гуру
26.08.16
09:12
(32) Чему тут думать то? Тебе же сказали в (11) как сделать!
35 Горогуля
 
26.08.16
09:13
(32) правильно! думать над запросами - признак слабоумия. писать текст запроса руками - повод для прострела коленки
36 Горогуля
 
26.08.16
09:14
(33) ты не путай сложность алгоритма со скоростью исполнения
37 Штурман
 
26.08.16
09:16
(34) я не совсем понял, что в (11) написано, т.е. мне надо таблицу обходить, проверяя равенство первой колонки и сравнивать значения второй колонки с предыдущей?
38 Горогуля
 
26.08.16
09:18
>Перебираешь в отсортированной табличке строки.
да, надо обходить
>На каждом шаге знаешь две строки - текущую и предыдущую.
это та, которая текущая и та, которая была перед ней
> Если ключ в первой колонке в этих двух строках различен,
отличаются ключи
>то в предыдущей строке искомые данные, которые надо слить в результат.
добавить текущую в результат
39 Рэйв
 
26.08.16
09:21
(5) блин проще сделать , чем объяснить:-)
лови пример
https://yadi.sk/d/WAhLO8rSuVmVw
40 Garykom
 
гуру
26.08.16
09:22

КолСтрок = тз.Количество();
Для НомСтр = 0 По КолСтрок-2 Цикл
ТекСтр = тз[НомСтр];
СледСтрока = тз[НомСтр+1];
Если ТекСтр.Колонка1<>СледСтрока.Колонка1 Тогда
  Сообщить(""+ТекСтр.Колонка1+" - "+ТекСтр.Колонка2);
КонецЕсли;
КонецЦикла;
ТекСтр = тз[КолСтрок-1];
Сообщить(""+ТекСтр.Колонка1+" - "+ТекСтр.Колонка2);
41 Рэйв
 
26.08.16
09:23
+(39) Это работающий модуль из обработки:

Процедура КнопкаВыполнитьНажатие(Кнопка)
    ДоКол1="ййй";
    ДоКол2="ййй";
    Для Каждого Стр из тз Цикл
        Если ДоКол1<>"ййй"  Тогда
            Если ДоКол1<>Стр.Колонка1 Тогда
                Нов=тз2.Добавить();
                Нов.Колонка1=ДоКол1;
                Нов.Колонка2=ДоКол2;
            КонецЕсли;    
        КонецЕсли;    
        ДоКол1=Стр.Колонка1;
        ДоКол2=Стр.Колонка2;
    Конеццикла;    
    Нов=тз2.Добавить();
    Нов.Колонка1=ДоКол1;
    Нов.Колонка2=ДоКол2;

КонецПроцедуры


Процедура ПриОткрытии()
   тз.Колонки.Добавить("Колонка1");
    тз.Колонки.Добавить("Колонка2");
   тз2.Колонки.Добавить("Колонка1");
    тз2.Колонки.Добавить("Колонка2");
    
    стр = тз.Добавить();
    стр.Колонка1 = "Первое";
    стр.Колонка2 = "A";
    стр = тз.Добавить();
    стр.Колонка1 = "Первое";
    стр.Колонка2 = "B";
    стр = тз.Добавить();
    стр.Колонка1 = "Второе";
    стр.Колонка2 = "C";
    стр = тз.Добавить();
    стр.Колонка1 = "Второе";
    стр.Колонка2 = "D";
    стр = тз.Добавить();
    стр.Колонка1 = "Второе";
    стр.Колонка2 = "E";
    стр = тз.Добавить();
    стр.Колонка1 = "Второе";
    стр.Колонка2 = "F";
    стр = тз.Добавить();
    стр.Колонка1 = "Третье";
    стр.Колонка2 = "G";
    стр = тз.Добавить();
    стр.Колонка1 = "Третье";
    стр.Колонка2 = "H";
    стр = тз.Добавить();
    стр.Колонка1 = "Третье";
    стр.Колонка2 = "I";
    
    тз.Сортировать("Колонка1, Колонка2");
    Элементыформы.тз.СоздатьКолонки();
    Элементыформы.тз2.СоздатьКолонки();
        
КонецПроцедуры
42 Garykom
 
гуру
26.08.16
09:24
(36) Не путаю но кто то написал "быстрее - почти наверняка" как оно будет быстрее запросом то?
43 Горогуля
 
26.08.16
09:25
(42) запросом оно будет быстрее. наверняка
44 Штурман
 
26.08.16
09:28
в общем, всем спасибо :)
45 Garykom
 
гуру
26.08.16
09:29
(43) Как хорошо... что пока есть такие всегда работа будет )) Такие кто выучил "запросы всегда быстрее" и все, дальше теорию изучать и практику не хочет )))
46 Горогуля
 
26.08.16
09:29
(45) всегда - это ты сам придумал
47 Штурман
 
26.08.16
09:30
(45) так почти везде в коде конфигураций 1с большей частью запросы, а вот всяких тз, массивов и тд не особо много
48 Garykom
 
гуру
26.08.16
09:32
(46) Готов поспорить на пиво что данная задачка будет быстрее на любых объемах быстрее "не запросами".

Если сравнивать на одном железе и одних данных, именно таких как приведены т.е. "простые строки".
49 Штурман
 
26.08.16
09:33
Кстати, вот вроде неплохая статейка о работе в 1с с универсальными коллекциями:

http://курсы-по-1с.рф/articles/работа-с-универсальными-коллекциями/
50 Горогуля
 
26.08.16
09:33
(48) спорить я с тобой не собираюсь, репутацией не вышел ;)
51 Garykom
 
гуру
26.08.16
09:36
(50) Не понял только кто не вышел репутацией ))

Суть что если ТЗ сильно большая то только передача данных внутрь запроса в ВТ займет дофига времени как и получение данных из запроса.

Но вот если исходные данные уже лежат в БД то логично использовать именно запросы для скорости получения данных, особенно если результат в ту же БД назад засунуть нуна.
Кaк может человек ожидaть, что его мольбaм о снисхождении ответит тот, кто превыше, когдa сaм он откaзывaет в милосердии тем, кто ниже его? Петр Трубецкой