использовать метод sum ()
df.groupby(['Fruit','Name']).sum()
Out[31]:
Number
Fruit Name
Apples Bob 16
Mike 9
Steve 10
Grapes Bob 35
Tom 87
Tony 15
Oranges Bob 67
Mike 57
Tom 15
Tony 1
Я проверил ваши коды и обнаружил, что это больше, чем просто 2 ключа, на самом деле вы можете воспроизвести его проще с помощью большего количества ключей; попробуйте одновременно нажать asdjkl (6 клавиш), и вы увидите еще больше беспорядка.
И я думаю, что проблема заключается в том, что цикл перерисовки реакции не работает со слушателем событий dom, что означает, что onKeyDown
и onKeyUp
запускаются всякий раз, когда он хочет, но реакция не перерисовывается при каждом их запуске. Просто войдите [...activeKeys, e.key]
и [...activeKeys].filter(i => i !== e.key)
, и вы увидите это.
Я думаю, что решение состоит в том, чтобы использовать простую локальную переменную для обновления activeKeys
, затем метод render
должен использовать эту переменную вместо результата хука, и, наконец, сделать forceUpdate в каждом onKeyDown
и [ 117], чтобы сделать реактивный повтор.
Оказывается, мне просто нужно было заменить useEffect
на useLayoutEffect
из документов :
Подпись идентична useEffect, но он запускается синхронно после всех мутаций DOM. Используйте это для чтения макета из DOM и синхронного повторного рендеринга. Обновления, запланированные внутри useLayoutEffect, будут сбрасываться синхронно, прежде чем браузер сможет рисовать.
BLOCKQUOTE>
Проблема в том, что вы используете простую форму setState(newValue)
, которая заменяет ваше состояние новым значением. Вы должны использовать функциональную форму setState( (prevState) => {} );
, потому что ваше новое состояние зависит от предыдущего состояния.
Попробуйте это:
const onKeyDown = e => {
if (!activeKeys.includes(e.key)) {
console.log("keydown", e.key, activeKeys);
setActiveKeys(prevActiveKeys => [...prevActiveKeys, e.key]);
}
};
const onKeyUp = e => {
console.log("keyup", e.key, activeKeys);
setActiveKeys(prevActiveKeys =>
[...prevActiveKeys].filter(i => i !== e.key)
);
};