Разместить в обратном порядке отображаемые значения std::map
От: Сыроежка  
Дата: 10.01.12 20:57
Оценка:
Как проще выполнить реверсию значений элементов для заданного контейнера std::map? То есть ключи остаются на месте, а меняются в обратном порядке отображаемые значения.

13.01.12 09:35: Перенесено из 'C/C++'
Меня можно встретить на www.cpp.forum24.ru
Re: Разместить в обратном порядке отображаемые значения std:
От: rm822 Россия  
Дата: 10.01.12 21:20
Оценка: 1 (1)
например так
(писал в броузере, если где накосячил просьба не пинать)
auto fwd = map.begin();
auto rev = map.rbegin();
for(size_t i=0; i < map.size()/2; ++i, ++fwd, ++rev)
  std::swap(fwd->second,rev->second);
Re[2]: Разместить в обратном порядке отображаемые значения s
От: Сыроежка  
Дата: 10.01.12 21:27
Оценка: :)))
Здравствуйте, rm822, Вы писали:

R>например так

R>(писал в броузере, если где накосячил просьба не пинать)
R>
R>auto fwd = map.begin();
R>auto rev = map.rbegin();
R>for(size_t i=0; i < map.size()/2; ++i, ++fwd, ++rev)
R>  std::swap(fwd->second,rev->second);
R>


Спасибо за пример. Но я наверное нечетко сформулировал свой исходный вопрос. Меня удивило, что в контейнере std::map нет функции-члена reverse Естественно я сделал предположение, что если такой функции-члена класса нет, то наверное легко эту операцию сделать с помощью стандартных алгоритмов. но стандартный алгоритм std::reverse по понятным причинам не подходит.
Поэтому и возник вопрос, как с помощью стандартных алгоритмов сделать подобную операцию для std::map. Может быть в boost такой алгоритм существует, если с помощью стандартных алгоритмов нужно исхитряться?
Меня можно встретить на www.cpp.forum24.ru
Re[3]: Разместить в обратном порядке отображаемые значения s
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 10.01.12 22:12
Оценка:
Здравствуйте, Сыроежка, Вы писали:

С>Спасибо за пример. Но я наверное нечетко сформулировал свой исходный вопрос. Меня удивило, что в контейнере std::map нет функции-члена reverse Естественно я сделал предположение, что если такой функции-члена класса нет, то наверное легко эту операцию сделать с помощью стандартных алгоритмов. но стандартный алгоритм std::reverse по понятным причинам не подходит.

С>Поэтому и возник вопрос, как с помощью стандартных алгоритмов сделать подобную операцию для std::map. Может быть в boost такой алгоритм существует, если с помощью стандартных алгоритмов нужно исхитряться?

Задача не совсем понятна, но попробую отгадать.
Вариант 1 — надо что-то сделать с элементами в обратном порядке
std::foreach( map.rbegin(), map.rend(), doSomething() );


Вариант 2 — сделать map с обратным порядком —
Тут надо просто компаратор другой для второго map'а задать.

Но вообще, это вроде очевидные решения, я наверно задачи не понял.
Маньяк Робокряк колесит по городу
Re[3]: Разместить в обратном порядке отображаемые значения s
От: rm822 Россия  
Дата: 10.01.12 22:13
Оценка:
С>Поэтому и возник вопрос, как с помощью стандартных алгоритмов сделать подобную операцию для std::map. Может быть в boost такой алгоритм существует, если с помощью стандартных алгоритмов нужно исхитряться?
ну есть там transform_iterator, но он какой-то замороченый
что-нибудь в таком стиле
struct MyTransform
{
  //здесь еще какая-то возня с тайпдефами должна быть
  MyValue& operator()(std::pair<MyKey,MyValue>& keyValue) const { key.second; }
};

std::reverse(boost::make_transform_iterator(map.begin(), MyTransform() ),boost::make_transform_iterator(map.end(), MyTransform() ));


можно конечно попробовать MyTransform заменить на
bind( &std::map<...>::value_type::second, _1 )
или
[](std::map<...>::value_type& pair) { return pair.second;});


по мне так все это выглядит одинаково мерзко и нечитабельно, даже если будет работать
Re[4]: Разместить в обратном порядке отображаемые значения s
От: Сыроежка  
Дата: 10.01.12 22:27
Оценка:
Здравствуйте, Marty, Вы писали:

M>Здравствуйте, Сыроежка, Вы писали:


С>>Спасибо за пример. Но я наверное нечетко сформулировал свой исходный вопрос. Меня удивило, что в контейнере std::map нет функции-члена reverse Естественно я сделал предположение, что если такой функции-члена класса нет, то наверное легко эту операцию сделать с помощью стандартных алгоритмов. но стандартный алгоритм std::reverse по понятным причинам не подходит.

С>>Поэтому и возник вопрос, как с помощью стандартных алгоритмов сделать подобную операцию для std::map. Может быть в boost такой алгоритм существует, если с помощью стандартных алгоритмов нужно исхитряться?

M>Задача не совсем понятна, но попробую отгадать.

M>Вариант 1 — надо что-то сделать с элементами в обратном порядке
M>
M>std::foreach( map.rbegin(), map.rend(), doSomething() );
M>


M>Вариант 2 — сделать map с обратным порядком —

M>Тут надо просто компаратор другой для второго map'а задать.

M>Но вообще, это вроде очевидные решения, я наверно задачи не понял.


Задача простая: для заданного контейнера std::map реверсировать отображаемые значения.
Хочу понять, почему такой алгоритм не включен в качестве функции-члена класса std::map. Если он не включен, то наверное предполагается, что сделать это просто с помощью стандартных алгоритмов. Ведь какие основные принципы включения или не включения алгоритмов к ачестве функций-членов контейнеров? Первое- это невозможность сделать данную операцию с помощью стандартного алгоритма. например, стандартный алгоритм std::sort требует наличия итераторов произвольного доступа. Так как в контейнере std::list итератор не является итератором произвольного доступа, то этот алгоритм включили в качестве функции-лена класса для контейнера std::list Второе — это если делать алгоритм членом класса, то можно достичь большей эффективности. Такие алгоритмы включены, например, в класс std::basic_string.
Поэтому и возник вопрос, раз алгоритм reverse не включен в контейнер std::map в качестве члена класса, то наверное его можно как-то достаточно просто реализовать с помощью стандартных алгоритмов? да причем так, чтобы каждый программист не открывал для себя заново велосипед.
Меня можно встретить на www.cpp.forum24.ru
Re[5]: Разместить в обратном порядке отображаемые значения s
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 10.01.12 23:49
Оценка: 1 (1)
Здравствуйте, Сыроежка, Вы писали:

С>Задача простая: для заданного контейнера std::map реверсировать отображаемые значения.

Таки расскажите, что значит реверсировать7

С>Хочу понять, почему такой алгоритм не включен в качестве функции-члена класса std::map. Если он не включен, то наверное предполагается, что сделать это просто с помощью стандартных алгоритмов. Ведь какие основные принципы включения или не включения алгоритмов к ачестве функций-членов контейнеров? Первое- это невозможность сделать данную операцию с помощью стандартного алгоритма. например, стандартный алгоритм std::sort требует наличия итераторов произвольного доступа. Так как в контейнере std::list итератор не является итератором произвольного доступа, то этот алгоритм включили в качестве функции-лена класса для контейнера std::list Второе — это если делать алгоритм членом класса, то можно достичь большей эффективности. Такие алгоритмы включены, например, в класс std::basic_string.

С>Поэтому и возник вопрос, раз алгоритм reverse не включен в контейнер std::map в качестве члена класса, то наверное его можно как-то достаточно просто реализовать с помощью стандартных алгоритмов? да причем так, чтобы каждый программист не открывал для себя заново велосипед.

map уже сортирован по ключу. итераторов произвольного доступа нет, и, имхо, не будет, если и будут, то с временем доступа O(N).

и задача "реверсировать" так и не раскрыта.
Маньяк Робокряк колесит по городу
Re: Разместить в обратном порядке отображаемые значения std:
От: jazzer Россия Skype: enerjazzer
Дата: 11.01.12 01:18
Оценка: 1 (1) +1
Здравствуйте, Сыроежка, Вы писали:

С>Как проще выполнить реверсию значений элементов для заданного контейнера std::map? То есть ключи остаются на месте, а меняются в обратном порядке отображаемые значения.


Зачем?
Если затем, чтоб обходить в обратном порядке, то есть rbegin/rend.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: Разместить в обратном порядке отображаемые значения s
От: andy1618 Россия  
Дата: 11.01.12 07:38
Оценка: 1 (1) -2
Здравствуйте, Сыроежка, Вы писали:

С>Меня удивило, что в контейнере std::map нет функции-члена reverse


Тут ничего удивительного нет. std::map — это ассоциативный массив (ключ-значение), работа с которым предполагается как с фиксированными парами с доступом по ключу.
Более того, в некоторых языках программирования ассоциативные массивы реализуются как хеш-таблицы, где вообще понятие "порядок ключей" не имеет смысла.
Подробности можно почитать здесь.
Re: Разместить в обратном порядке отображаемые значения std:
От: MasterZiv СССР  
Дата: 11.01.12 07:42
Оценка: 1 (1) +1 -5 :))) :)
> Как проще выполнить реверсию значений элементов для заданного контейнера
> std::map? То есть ключи остаются на месте, а меняются в обратном порядке

Порядок хранения элементов в std::map не определён. Обратным порядком для
неоределённого порядка будет также неопределённый порядок. Следовательно,
тебе ПРОСТО НЕ НУЖНО НИЧЕГО ДЕЛАТЬ.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Разместить в обратном порядке отображаемые значения s
От: Анатолий Широков СССР  
Дата: 11.01.12 08:06
Оценка:
Здравствуйте, MasterZiv, Вы писали:


>> Как проще выполнить реверсию значений элементов для заданного контейнера

>> std::map? То есть ключи остаются на месте, а меняются в обратном порядке

MZ>Порядок хранения элементов в std::map не определён. Обратным порядком для

MZ>неоределённого порядка будет также неопределённый порядок. Следовательно,
MZ>тебе ПРОСТО НЕ НУЖНО НИЧЕГО ДЕЛАТЬ.

Ты что-то путаешь. Порядок на множестве ключей определен и этот порядок для множества ключей данного экземпляра std::map изменить нельзя.
Re[5]: Разместить в обратном порядке отображаемые значения s
От: uzhas Ниоткуда  
Дата: 11.01.12 09:21
Оценка:
Здравствуйте, Сыроежка, Вы писали:

С>Задача простая: для заданного контейнера std::map реверсировать отображаемые значения.

если я правильно понял, то хочется из одного словаря сделать второй, у которого ключи будут старыми, а значения переставятся
первый же ответ rm822 дал хороший способ совершить данное действо (вариант inplace)

С>Хочу понять, почему такой алгоритм не включен в качестве функции-члена класса std::map.

1) лично мне никогда такое не требовалось, поэтому предположу, что задача не распространена, поэтому ее никто не просил
2) данный частный алгоритм реализуем штатными средствами (отсылаю к тому же rm822)

С>Второе — это если делать алгоритм членом класса, то можно достичь большей эффективности. Такие алгоритмы включены, например, в класс std::basic_string.

не очень представляю какие такие внутренние данные контейнера смогут помочь ускорить предложенный выше алгоритм, не ухудшив другие характеристики std::map. мне кажется он вполне себе оптимальным
для варианта, когда исходный словарь не меняется, а создается его копия можно было бы достичь лучшей производительности, скопировав внутреннее дерево, т.к. при этой операции форма дерева не меняется. меняются лишь ассоциированные данные. однако такими алгоритмами редко балуются из-за накладных расходов (immutable approach не в почете нынче)

С>Поэтому и возник вопрос, раз алгоритм reverse не включен в контейнер std::map в качестве члена класса, то наверное его можно как-то достаточно просто реализовать с помощью стандартных алгоритмов? да причем так, чтобы каждый программист не открывал для себя заново велосипед.

на велосипедах весь си++ и живет
Re[4]: Разместить в обратном порядке отображаемые значения s
От: baily Россия  
Дата: 11.01.12 11:47
Оценка: 1 (1) -1
Здравствуйте, andy1618, Вы писали:

A>Здравствуйте, Сыроежка, Вы писали:


С>>Меня удивило, что в контейнере std::map нет функции-члена reverse


A>Тут ничего удивительного нет. std::map — это ассоциативный массив (ключ-значение), работа с которым предполагается как с фиксированными парами с доступом по ключу.

A>Более того, в некоторых языках программирования ассоциативные массивы реализуются как хеш-таблицы, где вообще понятие "порядок ключей" не имеет смысла.
A>Подробности можно почитать здесь.

Непонятно, почему заминусовали данный ответ. Ну, конечно, можно придраться, что порядок элементов в map зависит от ключа и это иногда нужно.
Однако операции для map, которые переставляют значения для ключей типа reverse, уж совершенно лишены смысла. Ведь это совсем не то, что перебрать элементы
через rbegin, rend а совсем другое. Ясно, что такую задачу, когда это полезно придумать можно, но это не отвечает тому, для чего задумывался map.
С таким же основанием можно было бы потребовать добавить функции-член для подсчета среднего гармонического значения от элементов контейнера и т.д. и т.п
Re[6]: Разместить в обратном порядке отображаемые значения s
От: Сыроежка  
Дата: 11.01.12 12:17
Оценка:
Здравствуйте, Marty, Вы писали:

M>Здравствуйте, Сыроежка, Вы писали:


С>>Задача простая: для заданного контейнера std::map реверсировать отображаемые значения.

M>Таки расскажите, что значит реверсировать7

С>>Хочу понять, почему такой алгоритм не включен в качестве функции-члена класса std::map. Если он не включен, то наверное предполагается, что сделать это просто с помощью стандартных алгоритмов. Ведь какие основные принципы включения или не включения алгоритмов к ачестве функций-членов контейнеров? Первое- это невозможность сделать данную операцию с помощью стандартного алгоритма. например, стандартный алгоритм std::sort требует наличия итераторов произвольного доступа. Так как в контейнере std::list итератор не является итератором произвольного доступа, то этот алгоритм включили в качестве функции-лена класса для контейнера std::list Второе — это если делать алгоритм членом класса, то можно достичь большей эффективности. Такие алгоритмы включены, например, в класс std::basic_string.

С>>Поэтому и возник вопрос, раз алгоритм reverse не включен в контейнер std::map в качестве члена класса, то наверное его можно как-то достаточно просто реализовать с помощью стандартных алгоритмов? да причем так, чтобы каждый программист не открывал для себя заново велосипед.

M>map уже сортирован по ключу. итераторов произвольного доступа нет, и, имхо, не будет, если и будут, то с временем доступа O(N).


M>и задача "реверсировать" так и не раскрыта.


Так я в первом своем сообщении, и как мне представляется, в других сообщениях, ясно сказал, что реверсировать нужно отображаемые значения, то есть mapped_type, сохранив порядок ключей.
Меня можно встретить на www.cpp.forum24.ru
Re[6]: Разместить в обратном порядке отображаемые значения s
От: Сыроежка  
Дата: 11.01.12 12:27
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, Сыроежка, Вы писали:


С>>Задача простая: для заданного контейнера std::map реверсировать отображаемые значения.

U>если я правильно понял, то хочется из одного словаря сделать второй, у которого ключи будут старыми, а значения переставятся
U>первый же ответ rm822 дал хороший способ совершить данное действо (вариант inplace)

С>>Хочу понять, почему такой алгоритм не включен в качестве функции-члена класса std::map.

U>1) лично мне никогда такое не требовалось, поэтому предположу, что задача не распространена, поэтому ее никто не просил
U>2) данный частный алгоритм реализуем штатными средствами (отсылаю к тому же rm822)

С>>Второе — это если делать алгоритм членом класса, то можно достичь большей эффективности. Такие алгоритмы включены, например, в класс std::basic_string.

U>не очень представляю какие такие внутренние данные контейнера смогут помочь ускорить предложенный выше алгоритм, не ухудшив другие характеристики std::map. мне кажется он вполне себе оптимальным
U>для варианта, когда исходный словарь не меняется, а создается его копия можно было бы достичь лучшей производительности, скопировав внутреннее дерево, т.к. при этой операции форма дерева не меняется. меняются лишь ассоциированные данные. однако такими алгоритмами редко балуются из-за накладных расходов (immutable approach не в почете нынче)

С>>Поэтому и возник вопрос, раз алгоритм reverse не включен в контейнер std::map в качестве члена класса, то наверное его можно как-то достаточно просто реализовать с помощью стандартных алгоритмов? да причем так, чтобы каждый программист не открывал для себя заново велосипед.

U>на велосипедах весь си++ и живет

Да, вы правильно поняли задачу. Только изменение надо делать "на месте", не создавая второй контейнер.
Что касается первого предложенного варианта, то как раз он меня не устраивает, так как лично бы я сделал по-другому. например, можно не использовать для цикла размер контейнера. Второе — можно не использовать два типа итераторов в цикле, а воспользоваться одним типом итератора, так как он заведомо двусторонний и т.д. То есть получается, что у каждого программиста будет свое решение, и не обязательно корректное. Например, в алгоритме reverese (в его стандартной реализации) можно легко допустить оишбку, когда итератор, идущий от начала, "перескакивает итератор, идущий от конца последовательности. То есть не будет выполнено условие цикла. Это я к тому, что чем больше дается свободы в реализации алгоритма, тем больше вероятномть наличия ошибки в реализации. То есть получается, что каждый программист изобретает велосипед заново. Кроме того у такого доморощенного алгоритма могут быть разные названия, а потому для читающего код сразу будет трудно понять, а что именно эта функция делает, так как в разных проектах она будет называться поо-разному. То есть за названием функции не будет угадываться ее семантика. А это на мой взгляд существенный недостаток.
Любой стандартный алгоритм должен охватывать как можно больше типов контейнеров. И даже если у контейнера имеется собственная аналогичная функция-член, как, например, для контейнера std::basic_string функция-член find, стандартный алгоритм также желательно в общем случае должен работать с таким контейнером.
Меня можно встретить на www.cpp.forum24.ru
Re[5]: Разместить в обратном порядке отображаемые значения s
От: Сыроежка  
Дата: 11.01.12 12:30
Оценка:
Здравствуйте, baily, Вы писали:

B>Здравствуйте, andy1618, Вы писали:


A>>Здравствуйте, Сыроежка, Вы писали:


С>>>Меня удивило, что в контейнере std::map нет функции-члена reverse


A>>Тут ничего удивительного нет. std::map — это ассоциативный массив (ключ-значение), работа с которым предполагается как с фиксированными парами с доступом по ключу.

A>>Более того, в некоторых языках программирования ассоциативные массивы реализуются как хеш-таблицы, где вообще понятие "порядок ключей" не имеет смысла.
A>>Подробности можно почитать здесь.

B>Непонятно, почему заминусовали данный ответ. Ну, конечно, можно придраться, что порядок элементов в map зависит от ключа и это иногда нужно.

B>Однако операции для map, которые переставляют значения для ключей типа reverse, уж совершенно лишены смысла. Ведь это совсем не то, что перебрать элементы
B>через rbegin, rend а совсем другое. Ясно, что такую задачу, когда это полезно придумать можно, но это не отвечает тому, для чего задумывался map.
B>С таким же основанием можно было бы потребовать добавить функции-член для подсчета среднего гармонического значения от элементов контейнера и т.д. и т.п

Скажу сразу, лично я ничего не минусовал!

Но я совершенно не согласен с вашим утверждением. Реверсирование данных любого контейнера — это очень полезная вещь. например, даже в базах данных, имеющих доступ к записям по ключу, часто требуется создавать реверсивный набор, чтобы выполнить ту или иную задачу.
Меня можно встретить на www.cpp.forum24.ru
Re[2]: Разместить в обратном порядке отображаемые значения s
От: Сыроежка  
Дата: 11.01.12 12:32
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, Сыроежка, Вы писали:


С>>Как проще выполнить реверсию значений элементов для заданного контейнера std::map? То есть ключи остаются на месте, а меняются в обратном порядке отображаемые значения.


J>Зачем?

J>Если затем, чтоб обходить в обратном порядке, то есть rbegin/rend.

Я вас уверяю, что задачи, возникающие на практике. значительно разнообразнее, чем может представить ваша фантазия в данный момент!
Меня можно встретить на www.cpp.forum24.ru
Re[3]: Разместить в обратном порядке отображаемые значения s
От: jazzer Россия Skype: enerjazzer
Дата: 11.01.12 12:35
Оценка: 1 (1) :)
Здравствуйте, Сыроежка, Вы писали:

С>Здравствуйте, jazzer, Вы писали:


J>>Здравствуйте, Сыроежка, Вы писали:


С>>>Как проще выполнить реверсию значений элементов для заданного контейнера std::map? То есть ключи остаются на месте, а меняются в обратном порядке отображаемые значения.


J>>Зачем?

J>>Если затем, чтоб обходить в обратном порядке, то есть rbegin/rend.

С>Я вас уверяю, что задачи, возникающие на практике. значительно разнообразнее, чем может представить ваша фантазия в данный момент!


Этот комментарий, безусловно, всё прояснил, и главное, ответил на вопрос "зачем".
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: Разместить в обратном порядке отображаемые значения s
От: jazzer Россия Skype: enerjazzer
Дата: 11.01.12 12:39
Оценка:
Здравствуйте, rm822, Вы писали:

R>ну есть там transform_iterator, но он какой-то замороченый

и поэтому есть boost.range
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: Разместить в обратном порядке отображаемые значения s
От: uzhas Ниоткуда  
Дата: 11.01.12 12:40
Оценка:
Здравствуйте, baily, Вы писали:

B>Непонятно, почему заминусовали данный ответ. Ну, конечно, можно придраться, что порядок элементов в map зависит от ключа и это иногда нужно.

std::map — это не просто какой-то там ассоциативный контейнер, это контейнер, предоставляющий некие гарантии по сложности операций, по интерфейсу и по семантике
крайне интересным считаю документацию контейнеров от SGI : http://www.sgi.com/tech/stl/Map.html
там формально введена некая классификация контейнеров и вы можете убедиться, что std::map удовлетворяет моделям Unique Sorted Associative Container, Pair Associative Container
именно подобные модели позволяют для конкретно этого контейнера реализовывать алгоритмы, которые не прикрутишь к другим ассоциативным контейнерам типа хеш-таблиц
в частности, алгоритм ТС применим к std::map и не применим к хеш-таблицам, потому что там нет порядка ключей

B>Однако операции для map, которые переставляют значения для ключей типа reverse, уж совершенно лишены смысла.

операция не лишена смысла, в ней заинтересован ТС и уже дали даже один вариант реализации
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.