Перегруженный цепной оператор & lt; выход буферизации [дубликат]

Основываясь на превосходном решении [DMG], [6], здесь представлена ​​универсальная векторная (без петель) функция, которая разбивает столбец кадра данных на несколько строк и объединяет его с исходным фреймворком данных.

def change_column_order(df, col_name, index):
    cols = df.columns.tolist()
    cols.remove(col_name)
    cols.insert(index, col_name)
    return df[cols]

def split_df(dataframe, col_name, sep):
    orig_col_index = dataframe.columns.tolist().index(col_name)
    orig_index_name = dataframe.index.name
    orig_columns = dataframe.columns
    dataframe = dataframe.reset_index()  # we need a natural 0-based index for proper merge
    index_col_name = (set(dataframe.columns) - set(orig_columns)).pop()
    df_split = pd.DataFrame(
        pd.DataFrame(dataframe[col_name].str.split(sep).tolist())
        .stack().reset_index(level=1, drop=1), columns=[col_name])
    df = dataframe.drop(col_name, axis=1)
    df = pd.merge(df, df_split, left_index=True, right_index=True, how='inner')
    df = df.set_index(index_col_name)
    df.index.name = orig_index_name
    # merge adds the column to the last place, so we need to move it back
    return change_column_order(df, col_name, orig_col_index)

Пример:

df = pd.DataFrame([['a:b', 1, 4], ['c:d', 2, 5], ['e:f:g:h', 3, 6]], 
                  columns=['Name', 'A', 'B'], index=[10, 12, 13])
df
        Name    A   B
    10   a:b     1   4
    12   c:d     2   5
    13   e:f:g:h 3   6

split_df(df, 'Name', ':')
    Name    A   B
10   a       1   4
10   b       1   4
12   c       2   5
12   d       2   5
13   e       3   6
13   f       3   6    
13   g       3   6    
13   h       3   6    

Обратите внимание, что он сохраняет исходный индекс и порядок столбцов. Он также работает с dataframes, которые имеют непоследовательный индекс.

8
задан LowTechGeek 19 January 2012 в 20:22
поделиться

5 ответов

Поведение вашего кода неуказано в соответствии со стандартом C ++.

Объяснение

Следующее (я удалил std::endl для простоты)

std::cout << "Hello, world!" << print( std::cout ); 

эквивалентно этому:

std::operator(operator<<(std::cout, "Hello, World!"), print(std::cout));

, который является вызовом функции, передавая два аргумента:

  • Первый аргумент: operator<<(std::cout, "Hello, World!")
  • Второй аргумент: print(std::cout)

Теперь в стандарте не указывается порядок, в котором оцениваются аргументы. Это неуказано . Но ваш компилятор сначала оценивает второй аргумент, поэтому он сначала печатает «Как вы?» , оценивая второй аргумент на значение типа std::ostream&, которое затем передается вызову (это значение является самим объектом std::cout).

Почему шестнадцатеричный вывод?

Вы получаете шестнадцатеричный вывод, потому что второй аргумент оценивается как std::cout, который печатается как шестнадцатеричное число, потому что std::cout неявно преобразуется в значение указателя типа void*, поэтому оно печатается как шестнадцатеричное число.

Попробуйте следующее:

void const *pointer = std::cout; //implicitly converts into pointer type!
std::cout << std::cout << std::endl;
std::cout << pointer << std::endl;

It будет печатать одинаковое значение для обоих. Например, этот пример в ideone печатает это:

0x804a044
0x804a044 

Также обратите внимание, что я не использовал явное cast; скорее std::cout - неявно преобразован в тип указателя.

Надеюсь, что это поможет.


Каков правильный способ записи функции, которая вставляет данные в ostream, но которая также может связываться с оператором & lt ;

Когда это зависит от того, что вы подразумеваете под цепочкой? Очевидно, что следующее не будет работать (как описано выше):

std::cout << X << print(std::cout) << Y << Z; //unspecified behaviour!

Независимо от того, как вы пишете print().

Однако это четко определено:

print(std::cout) << X << Y << Z; //well-defined behaviour!
5
ответ дан Nawaz 23 August 2018 в 16:55
поделиться

В вашем заявлении std::cout << "Hello, world!" << print( std::cout ) << std::endl не определено, происходит ли std::cout << "Hello, world!" до или после print( std::cout ). Вот почему порядок может быть не таким, каким вы ожидаете.

Значение hex исходит из того факта, что вы также выполняете std::cout << std::cout (print возвращает std::cout, который подается в << цепь). Правая рука std::cout преобразуется в void * и печатается на выходе.

1
ответ дан bames53 23 August 2018 в 16:55
поделиться

Это сработает, чтобы объединить print с << и управлять порядком:

print( std::cout << "Hello, world!" ) << std::endl;

Или, если вы хотите, чтобы функция, вызываемая с помощью <<, см. ответ Йоахима.

1
ответ дан Ben Voigt 23 August 2018 в 16:55
поделиться

Причина в том, что ваша функция print () будет вычисляться до остальной части инструкции и возвращать ссылку на cout, которая тогда фактически печатается как указатель (cout & lt; cout). Этот порядок оценки на самом деле является неуказанным поведением, но, похоже, имеет место с вашим компилятором.

Что касается определения функции «известно» потоком, которая фактически определила поведение с одинаковой функциональностью, это сработает; / g2]

#include <iostream>

template <class charT, class traits>
  std::basic_ostream<charT,traits>& print ( std::basic_ostream<charT,traits>& os )
{
        os << " How are you?" << std::endl;
        return os;
}

int main() {
  std::cout << "Hello, world!" << print << std::endl;
}

См. также этот ответ для более подробной информации о том, что «неопределенный» на самом деле означает в этом случае.

2
ответ дан Community 23 August 2018 в 16:55
поделиться

Шестнадцатеричный вывод

До C ++ 11 класс std::ostream имеет функцию преобразования в void*. Поскольку ваша функция print возвращает std::ostream&, при оценке std::cout << print(...) возвращаемое значение std::ostream l неявно преобразуется в void*, а затем выводится как значение указателя. Вот почему есть шестнадцатеричный вывод.

Поскольку C ++ 11, эта функция преобразования заменяется на явную функцию преобразования на bool, поэтому попытка вывести std::ostream.

Порядок оценки

До C ++ 17 перегруженный оператор считается вызовом функции для анализа порядка оценки и порядка оценки различных аргументов вызов функции не указан. Поэтому не странно, что сначала оценивается функция print, из-за чего вывод How are you? выводится первым.

Поскольку C ++ 17, порядок оценки операндов оператора << строго из слева направо, а операнды перегруженного оператора имеют тот же порядок оценки, что и у булитного входа (см. подробнее здесь ). Таким образом, ваша программа всегда будет получать результат (предполагается, что print возвращает что-то, что может быть выведено)

Hello, world! How are you?
something returned by print

LIVE EXAMPLE

1
ответ дан xskxzr 23 August 2018 в 16:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: