动态更改Streamlit.multiselectbox选项

4

我在我的Streamlit应用程序侧边栏中有一个多选框。以下不失一般性:

  • 我有10个选项可以放在这个多选框中(这些数字是1...10)
  • 用户可能不能同时选择12

因此,如果选择了1,我想将2从可选项列表中删除,但是Streamlit似乎没有这种功能,所以我尝试将其包装在循环中,但也失败了(DuplicateWidgetID: There are multiple identical st.multiselect widgets with the same generated key.):

options = [1,2,3,4,5,6,7,8,9,10]

space = st.sidebar.empty()
answer, _answer = [], None
while True:
    if answer != _answer:
        answer.append(space.multiselectbox("Pick a number",
                                           options,
                                           default=answer
                                           )
                      )
        options = [o for o in options if o not in answer]
        if 1 in options:
            if 2 in options: options.remove(2)
        if 2 in options:
            if 1 in options: options.remove(1)
        _answer = answer[:]

你有什么想法可以实现这个目标吗?


看起来这似乎不可能仅使用StreamLit实现。 - inspectorG4dget
用户不能同时选择1和2,您如何向用户传达这一信息? - ferdy
你如何向用户传达这个信息?通过在用户选择选项1时禁用选项2,使得选项2不再可选。这将允许更复杂的互斥逻辑。 - inspectorG4dget
我在我的修订答案中提供了第二种方法,这不够吗? - ferdy
答案已更新,添加了第三种方法,以删除选择了1或2的2或1。 - ferdy
1个回答

1

方法1

这里有一种方法,提供小部件上的帮助,并允许用户选择1和2,但我们必须过滤掉2,如果两者都被选中。然后,您可以直接使用经过验证的选择。

代码
import streamlit as st

ms = st.sidebar.multiselect('Pick a number',  list(range(1, 11)),
    help='Choose either 1 or 2 but not both. If both are selected 1 will be used.')

if 1 in ms and 2 in ms:
    ms.remove(2)

st.write('##### Valid Selection')
st.write(str(ms))
输出

将鼠标悬停在?上以显示帮助信息。

enter image description here

方法2

使用单选按钮选择选项1或2,其余选项使用多选框。

代码
import streamlit as st

rb = st.sidebar.radio('Pick a number', [1, 2])

ms = st.sidebar.multiselect('Pick a number',  list(range(3, 11)))

selected = ms
selected.append(rb)

st.write('##### Valid Selection')
st.write(str(selected))
输出

在此输入图片描述

方法三

当选择 1 时,删除 2,然后重新运行以更新选项。同样地,当选择 2 时,删除 1 并重新运行以更新选项。

代码
import streamlit as st


init_options = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


if 'options' not in st.session_state:
    st.session_state.options = init_options
if 'default' not in st.session_state:
    st.session_state.default = []


ms = st.sidebar.multiselect(
    label='Pick a number',
    options=st.session_state.options,
    default=st.session_state.default
)

# If 1 is selected, remove the 2 and rerun.
if 1 in ms:
    if 2 in st.session_state.options:
        st.session_state.options.remove(2)
        st.session_state.default = ms
        st.experimental_rerun()

# Else if 2 is selected, remove the 1 and rerun.
elif 2 in ms:
    if 1 in st.session_state.options:
        st.session_state.options.remove(1)
        st.session_state.default = ms
        st.experimental_rerun()


st.write('##### Valid Selection')
st.write(str(ms))
输出

输入图像描述


虽然这是解决UX问题的一种非常清晰的方式(即告知用户问题),但从技术上讲,它并不能限制用户做出错误的选择。因此,尽管在其他方面有所帮助,但它并不是问题的答案。 - inspectorG4dget
在答案中添加了第二种方法来解决这个问题。 - ferdy
添加了第三个方法,用于删除选择了1或2的情况下的2或1。 - ferdy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接