ulidtko 01.08.2012 13:22

std::vector<int> vec;
//...
vec.erase(std::remove(vec.begin(), vec.end(), value));

Форденька, ну за что, за что мне весь этот пиздец //-___-\\

Compare to:

>>> ints = [1,2,3]
>>> ints.remove(2)
>>> ints
[1, 3]

1. 0xd34df00d 01.08.2012 13:22 Azoth_primary

Причем ты мудак и сделал все неправильно.

2. 0xd34df00d 01.08.2012 13:23 Azoth_primary

vec.erase (std::remove (...), vec.end ()); для случая, когда больше одного значения удовлетворяет.

3. DZhon0xd34df00d /2 01.08.2012 13:24

лол, плюсую

4. ulidtko0xd34df00d /2 01.08.2012 13:26

да-да, про пример в http://en.cppreference.com/w/cpp/algorit... я вообще молчу, настолько охуел от него

5. 0xd34df00dulidtko /4 01.08.2012 13:26 Azoth_primary

А что?

6. DZhonulidtko /4 01.08.2012 13:27 Psi+

что с ним?

7. ulidtko0xd34df00d /5 01.08.2012 13:38

как это работает? std::remove возвращает итератор на что, на элементы, равные value? каким хуем они тогда оказываются в конце контейнера? >_<

8. 0xd34df00dulidtko /7 01.08.2012 13:40 Azoth_primary

remove перемещает элементы, удовлетворяющие предикату, в конец контейнера, и возвращает итератор на первый такой перемещенный элемент.
Ты ж сам ссылку привел на cppreference. Вникай в тамошний код до просветления :3

9. ulidtkoulidtko /7 01.08.2012 13:40

или std::remove возвращает итераторы типа как бы не по очереди, а сначала-все-остальные-потом-подходящие-по-критерию по очереди?

10. DZhonulidtko /7 01.08.2012 13:40 Psi+

std::remove тасует элементы, убирая в конец все, что "удаляется", возвращает итератор, указывающий на конец оставшихся элементов. erase-у передается он, как начало и старый конец, как конец. За счет этого стирается сразу блок.

11. 0xd34df00dulidtko /9 01.08.2012 13:40 Azoth_primary

Че блядь.

12. ulidtko0xd34df00d /8 01.08.2012 13:41

как он их перемещает? он не может менять контейнер же.

13. DZhonulidtko /12 01.08.2012 13:41 Psi+

Может.

14. 0xd34df00dulidtko /12 01.08.2012 13:42 Azoth_primary

С чего бы это?

15. ulidtkoDZhon /10 01.08.2012 13:42

ага, ну я так и понял. И ВНЕЗАПНО .end() этого итератора совпадает с .end() нашего исходного итератора, вообще охуеть блядь.

16. DZhonulidtko /15 01.08.2012 13:42 Psi+

» И ВНЕЗАПНО .end() этого итератора совпадает с .end() нашего исходного итератора, вообще охуеть блядь
ШТО ?

17. 0xd34df00dulidtko /15 01.08.2012 13:42 Azoth_primary

> end() итератора
Чтоблядь.

Хотя, возможно, ты имел ввиду, что если элементов не найдется, то будет vec.erase (end, end); И что тебя смущает?

18. 0xd34df00d 01.08.2012 13:45 Azoth_primary

Олсо, почему-то хочется запостить сюда это → :3

19. DZhon0xd34df00d /18 01.08.2012 13:45 Psi+

Ваганизация треда.

20. 0xd34df00d0xd34df00d /17 01.08.2012 13:46 Azoth_primary

Собственно, достаточно просто помнить, что STL работает с полуоткрытыми интервалами, и удаление [end; end) ничего не меняет, очевидно.

21. ulidtkoDZhon /13 01.08.2012 13:46

в самом тупом и простом случае не меняет. И собственно нужный эффект не этим достигается, не свапаньем элементов в контейнере, а очередностью возврата итераторов.

22. 0xd34df00dulidtko /21 01.08.2012 13:47 Azoth_primary

> очередностью возврата итераторов
Блядь што.

Итератор возвращается там один раз. Нет тут никаких yield и всего такого.

23. magog 01.08.2012 13:48 Azoth@Work

не слушай этих плюсоблядей. Они люди потерянные для общества. Куда проще сделать просто remove [элемент]. Правда не понятно, как сделать удаление элементов только в части массива, а не во всем, но похуй. Питону это и не надо. Так что все ты правильно возмущаешься

24. ulidtko0xd34df00d /17 01.08.2012 13:50

нет, я не об этом. std::remove возвращает что? некий свой итератор со своим поведением. Который не совпадает с итератором, возвращаемым vec.begin(). Почему тогда его специальное значение, означающее конец итерирования, совпадает с vec.end()? Это ведь разные итераторы.

25. DZhonulidtko /21 01.08.2012 13:50 Psi+

Хуйню сказал, бро. Покури Possible implementation, представляя, что там не итераторы, а указатели.

26. ulidtko0xd34df00d /22 01.08.2012 13:50

гагага, а yield с помощью ++ не хочешь?

27. 0xd34df00dulidtko /24 01.08.2012 13:50 Azoth_primary

Щто.

28. DZhonulidtko /24 01.08.2012 13:51 Psi+

почему это у него свое поведение ? О_О

29. DZhonulidtko /24 01.08.2012 13:52 Psi+

>ForwardIterator result = first; С этого места же видно, что это итератор того же типа, а значит и поведения, что и переданы при вызове.

30. ulidtkomagog /23 01.08.2012 13:52

> Правда не понятно, как сделать удаление элементов только в части массива, а не во всем
чего непонятного-то, навешиваешь какой-нибудь range adaptor (например, самый простой slice syntax в питоне) и удаляешь, элементарно.

31. DZhonmagog /23 01.08.2012 13:53

ой ёлки, открой для себя слайсы.

32. ulidtkoDZhon /28 01.08.2012 13:53

потому что он после ++ возвращает не то, что возвращает результат vec.begin().

33. ulidtkoDZhon /25 01.08.2012 13:55

я не вижу, где и как в Possible implementations происходит перемещение заматченых элементов в конец.

34. DZhonulidtko /32 01.08.2012 13:56 Psi+

Нихуя не понял, все три итератора vec.begin(), vec.end() и внутренний result указывают на одну коллецию! Но на разные ее позиции. Почему это разное поведение ?

35. DZhonulidtko /33 01.08.2012 13:57 Psi+

Здесь: if (!p(*first)) {
*result++ = *first;
}
Нет, ну правда, представь, что это сишка и ForwardIterator ~ char * какой-нибудь.

36. ulidtkoDZhon /35 01.08.2012 14:01

да, вчитался уже. Оно перезаписывает контейнер, сдвигая элементы поверх заматченных. В конце остается мусор. Из функции возвращается указатель на начало мусора.

Пиздец-пиздец, нахуй так жить, посоны.

37. DZhonulidtko /36 01.08.2012 14:01 Psi+

Вот сейчас все верно.

38. ulidtkoDZhon /37 01.08.2012 14:02

— не прошло и сорока коментов. Блюю.

39. 0xd34df00dulidtko /38 01.08.2012 14:09 Azoth_primary

Питонируешь.

40. ulidtkoDZhon /37 01.08.2012 14:09

уже сам факт того, что выставляемые интерфейсы сложно понять, если не смотреть в possible implementation, говорит о крайне хуевом дизайне. Это если не говорить о том, что эти интерфейсы вообще излишни как абстракции, поскольку по всей стандартной библиотеке подразумевают единственный способ реализации.

41. ulidtko0xd34df00d /39 01.08.2012 14:10

если бы. Питонировал бы с радостью (items.remove(item)), но приходится жрать говно. :(

42. DZhonulidtko /40 01.08.2012 14:11 Psi+

Все претензии Степанову, он художник.
» Это если не говорить о том, что эти интерфейсы вообще излишни как абстракции, поскольку по всей стандартной библиотеке подразумевают единственный способ реализации.
Нет, не подразумевают.

43. ulidtkoDZhon /42 01.08.2012 14:13

подразумевают. Посмотри на требования по сложности к любому из стандартных контейнеров, они прямо кричат Я ДЕРЕВО, Я СПИСОК, Я ХЕШТАБЛИЦА этц.

44. DZhonulidtko /43 01.08.2012 14:15 Psi+

Посмотри, как сделано std::copy в студии, например.

45. ulidtkoulidtko /43 01.08.2012 14:17

то есть, не Я ДЕРЕВО, а ЭТОТ (оче дохуя абстрактный) КОНТЕЙНЕР НЕЛЬЗЯ РЕАЛИЗОВАТЬ ИНАЧЕ ЧЕМ СБАЛАНСИРОВАННЫМ ДЕРЕВОМ.

Например. Или любой из тех же стандартных алгоритмов, лол. Они «абстрагируют» в среднем 5-10 строчек кода, которые просто невозможно написать иначе, не нарушив требования интерфейса. Говно это, а не абстракции.

46. DZhonulidtko /45 01.08.2012 14:20 Psi+

тот же unordered_set как только не реализовывали, что EA, что в boost, что в STLPort. А уж про то, что алгоритмы неспециализированы — тут совсем мимо. Смотри std::copy, смотри std::fill. Кроме того, можно тот же find прокрутить быстрее, если распознать на входе итераторы от set, например. Вызвав бинарный поиск у самого set вместо тупой линейщинки.

47. ulidtkoDZhon /46 01.08.2012 14:26

посмотрел std::copy, std::fill, std::transform, везде узнаваемые циклы. В точности такие, как и подразумевает спецификация. Ну, плюс, дебажный range checking да специализации^W function overloads для char*, unsigned char*.

template<class _FwdIt, class _Ty> inline
void __CLRCALL_OR_CDECL _Fill(_FwdIt _First, _FwdIt _Last, const _Ty& _Val)
{ // copy _Val through [_First, _Last)
_DEBUG_RANGE(_First, _Last);
for (; _First != _Last; ++_First)
*_First = _Val;
}

inline void __CLRCALL_OR_CDECL _Fill(_Out_capcount_x_(_Last-_First) char *_First,
_In_opt_ char *_Last, int _Val)
{ // copy char _Val through [_First, _Last)
_DEBUG_RANGE(_First, _Last);
::memset(_First, _Val, _Last — _First);
}

//...

48. ulidtkoDZhon /46 01.08.2012 14:27

tell me moar про реализации unordered_set

49. DZhonulidtko /47 01.08.2012 14:28 Psi+

Циклы ок, но я как раз про версии для примитивов и дебажные кишки. Это уже не описано в стандарте, но и не нарушает его!

50. DZhonulidtko /48 01.08.2012 14:28 Psi+

Это поискать надо, вечерком, думаю, кину.

51. ulidtkoDZhon /49 01.08.2012 14:37

с итераторами в виде генераторов (а не указателей) свободы реализации было бы way more, как мне кажется.

Но я вроде уже начинаю понимать tradeoff между лоулевельностью-байтоебством и абстрактностью-удобством использования. Наверное. Хоть и не согласен с ним. Не должно его здесь быть. Получать производительность можно без жертв в удобстве.

52. DZhonulidtko /51 01.08.2012 14:38 Psi+

Ну да, это просто компромисс. В Qt есть Java-style итераторы, если хочется что-то другое еще.

53. DZhonulidtko /48 01.08.2012 17:15

Вот тут про старые реализации хэширующих контейнеров, обрати внимание:

http://attractivechaos.wordpress.com/200...

"Open addressing vs. chaining hash. Khash and google hash implement open addressing hash while the remaining implement chaining hash. In open addressing hash, the size of each bucket equals the size of a key plus 0.25 byte. Google sparsehash further compresses unused bucket to 1 bit, achieving high memory efficiency. In chaining hash, the memory overhead of each bucket is at least 4 bytes on 32bit machines, or 8 bytes on 64bit machines. However, chaining hash is less affected when the hash table is nearly full. In practice, both open addressing and chaining hash occupy similar memory under similar speed. Khash takes less peak memory mainly due to its advanced technique in rehashing which reduces memory usage. So far as speed is concerned, chaining hash may have fewer comparison between keys. We can see this from the fact that the speed of chaining hash approaches that of open addressing hash on string keys but much slower on integer keys."

И опять же, в стандарте не сказано, использовать ли открытую адресацию или цепочки для разрешения коллизий. Правда, насколько я видел, в студии цепочками сделано. В GCC не видал.

54. 238328 01.08.2012 17:36

я бы не стал использовать метод из питона нигде, кроме скрипткид-скриптов

55. 238328magog /23 01.08.2012 17:38

проиграл

56. ulidtko238328 /54 01.08.2012 17:57

почему?

57. 0xd34df00dulidtko /56 01.08.2012 17:57 Aedalus

Потому что питон негде использовать, кроме как в 10-строчных скриптах.

58. 238328ulidtko /56 01.08.2012 17:57 3935621841343840597335202

не эффективно, лучше запилить решение на другой структуре данных или пересмотреть работу алгоритма :cf:

59. ulidtko238328 /58 01.08.2012 17:58

штосука, черезчур толсто!

60. ulidtko0xd34df00d /57 01.08.2012 17:59

а ты так сразу и повёлся. ЛОХ

61. 238328ulidtko /59 01.08.2012 17:59 3935621841343840597335202

я серьёзно, приведи мне пример, где данный способ будет лучшим

62. ulidtko238328 /61 01.08.2012 18:16

лучшим чем что?

63. 238328ulidtko /62 01.08.2012 18:21 3935621841343840597335202

чем плюсы)))

64. ulidtko238328 /63 01.08.2012 20:14

items.erase(std::remove(items.begin(), items.end(), value));
VS
items.remove(value)

привёл.

65. 238328ulidtko /64 01.08.2012 23:00 12630156161343861477638749

ну что, вековая проблема решена — плюсы сосут у питона. Расходимся

Do you really want to delete ?