Left priority and space recognition in dropdown search

I am re-asking the question posted by meaydemi at Left priority in dropdown search. My dropdown search labels include ~5000 stock ticker symbols. When I type M (or any letter that isn’t A), I want to see the stocks beginning with M before the dozens or hundreds of single ticker symbols that have an M inside it.

Is there any way to do a left-priority search, and if not, I’d really think that is a critical option to add without too much difficulty. I can see the benefit of finding pattern matches in the center of the string if that’s all you find, but those should be placed behind front matches.

A second thing I’ve noticed is that the search seems to be ignoring spaces. In this case if I typed "SYM " (SYM being hypothetical for anything) it would match all strings with SYM inside (space or not) and not isolate the label that is “SYM - Corporation Name”. If there is any way to make this work properly now, or in the future that would be helpful.

chriddyp pointed me to the Dynamic Options example on https://dash.plotly.com/dash-core-components/dropdown and I solved it using:

return [o for o in options if re.match(search_value, o[“label”], re.IGNORECASE)]

for front matches only or:

opt = [o for o in options if re.match(search_value, o[“label”], re.IGNORECASE)]
opt.extend([o for o in options if o not in opt and search_value in o[“label”]])
return opt

for front matches, then body matches

1 Like

hi marketemp,
I’m interested in the same topic, I used your solution but the error message ask about the ‘re’ you are using.
Is there any component that is needed to import as ‘re’?
Thanks!

import re

it is the python regular expressions module - https://docs.python.org/3/library/re.html

Hi marketemp,
Thanks !!! everyday I learn new basic things :joy: :joy:
It works Perfect !!!

Thanks again.

Hi @marketemp

Here is what I created and seems to be working fine. When I type the name of the companies they pop up. Hope this helps.

import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
from pprint import pprint

from pandas_datareader import data as web
from datetime import datetime as dt
import FundamentalAnalysis as fa
api_key = "XXXX"

app = dash.Dash('Financial Market')
items = ['freeCashFlow', 'grossProfitRatio']

options=[
            {'label': 'Apple Inc', 'value': 'AAPL'},
            {'label': 'Tesla Motors', 'value': 'TSLA'},
            {'label': 'Intel Inc.', 'value': 'INTC'},
        ]

app.layout = html.Form(autoComplete="off", children=[
    dcc.Dropdown(
        id='textarea-state-example',
        clearable=True,
        value='AAPL',
        style={'width': '100%', 'height': 40, 'display':'flex', 'align-items': 'center', 'justify-content': 'center'}
    ),
    dcc.Graph(id=items[0]), dcc.Graph(id=items[1])
], style={'width': '250'})


class SearchFailed(Exception):
    def __init__(self, m):
        self.message = m
    def __str__(self):
        return self.message

@app.callback(
    dash.dependencies.Output("textarea-state-example", "options"),
    [dash.dependencies.Input("textarea-state-example", "search_value")],
)
def update_options(search_value):
    if not search_value:
        try:
            raise SearchFailed('Oops')
        except SearchFailed as failedSearch:
            print (failedSearch)
    if search_value:
        return [o for o in options if search_value.upper() in o["label"].upper()]
    else:
        return []


for i in range(len(items)):
    @app.callback(Output(items[i], 'figure'), [Input('textarea-state-example', 'value')])
    def update_graph(selected_dropdown_value):
        selected_dropdown_value = selected_dropdown_value.upper()
        ctx = dash.callback_context
        output_type = ctx.outputs_list['id']

        if output_type == 'freeCashFlow':
            statement = fa.cash_flow_statement(selected_dropdown_value, api_key, period="annual")
        else:
            statement = fa.income_statement(selected_dropdown_value, api_key, period="annual")

        return {
            'data': [{
                'x': statement.columns,
                'y': statement.loc[output_type]
            }],
            'layout': {'margin': {'l': 40, 'r': 40, 't': 40, 'b': 40}}
        }


app.css.append_css({'external_url': 'https://codepen.io/chriddyp/pen/bWLwgP.css'})

if __name__ == '__main__':
    # app.run_server()
    app.run_server(debug=True)

Hi @rozi,

Thanks, I definitely have this working already. The Possible bug in dcc.Dropdown quandary is to have it working with

options=[
            {'label': 'AAPL', 'value': 'AAPL'},
            {'label': 'TSLA', 'value': 'TSLA'},
            {'label': 'INTC', 'value': 'INTC'},
        ]

and to have the right ticker come up even when you type the full company name. As you can see in my example, I definitely have the Ticker->Name mapping done using another dict but even when my update would return TSLA when typing Tes as indicated within my print examples, something within dash filters it beyond that and TSLA is not an option in the dropdown.