Отфильтровать страны в правильном порядке в JavaScript? - PullRequest
0 голосов
/ 28 июня 2019

У меня есть список стран, по которым я фильтрую, чтобы сначала получить наилучший результат на основе входного термина.Я использую 2 примера, чтобы показать проблему.Ищите термин unit или in, и вы увидите, что ожидаемый порядок возврата названий стран неверен.Ожидаемые результаты должны вернуть те названия стран, которые начинаются с term, а после этого приоритета вернуть страны с частичными совпадениями строк term.Вот код с terms, текущими результатами и ожидаемыми результатами в первых 2 комментариях ниже:

const {observable, action, computed} = mobx;
const {observer} = mobxReact;

@observer
class Country extends React.Component {
    /*
     1. Type term: 'unit'
        Results:
        - Emirates, The United Arab
        - United States
        - The United Kingdom
        SHOULD BE:
        - United States (this should be first since it starts with the term 'unit')
        - The United Kingdom (this should be second since term 'unit' occurs in the name before "Emirates, The United Arab")
        - Emirates, The United Arab

     2. Type term: 'in'
        Results:
        - China
        - India
        - The United Kingdom
        SHOULD BE:
        - India (this should be first since it starts with the term 'in')
        - China (this should be second since 'in' term occurs in the name before "The United Kingdom")
        - The United Kingdom
    */

    @observable filterTermValue = '';
    @observable countriesList = [
      {'slug': 'amsterdam', 'name': 'Amsterdam'},
      {'slug': 'china', 'name': 'China'},
      {'slug': 'uae', 'name': 'Emirates, The United Arab'},
      {'slug': 'iceland', 'name': 'Iceland'},
      {'slug': 'india', 'name': 'India'},
      {'slug': 'usa', 'name': 'United States'},
      {'slug': 'uk', 'name': 'The United Kingdom'},
      {'slug': 'vienna', 'name': 'Vienna'}
    ];

    @computed get filtered() {
      let filteredList = this.countriesList.filter(
        t=>t.name.toLowerCase().indexOf(this.filterTermValue)>-1
      );

      return filteredList;
    }

    render() {
        return (
          <div>
              Term: <input placeholder="Start typing country"
                 onKeyUp={this.onChangeFilterTerm} />

              {this.filtered.map(country =>
                  <div key={country.slug}>
                    <p>{country.name}</p>
                  </div>
              )}
          </div>
        )
    }


    @action onChangeFilterTerm = (e) => {
        this.filterTermValue = e.target.value.toLowerCase();
    }
}

ReactDOM.render(
  <Country />,
  document.body
);

Вот скрипка

Любая идея, как обновить функцию filtered(), чтобы правильно вернуть ожидаемые результаты?

Ответы [ 2 ]

1 голос
/ 28 июня 2019

Похоже, вам нужно отсортировать возвращаемый массив в методе filtered. Взглянув на примеры использования, которые вы упомянули в своем вопросе, я думаю, вы можете отсортировать массив по индексу, с которого начинается совпадение.

Итак, ваш filtered метод может выглядеть так:

@computed get filtered() {
    return this.countriesList
        .filter(t => t.name.toLowerCase().indexOf(this.filterTermValue) >-1)
        .sort((a, b) => a.name.toLowerCase().indexOf(this.filterTermValue) - b.name.toLowerCase().indexOf(this.filterTermValue));
}
0 голосов
/ 28 июня 2019

Попробуйте это:

@computed get filtered() {
  let filteredList = this.countriesList.filter(
    t=>t.name.toLowerCase().indexOf(this.filterTermValue)>-1
  ).sort(
    (a, b) => a.name.toLowerCase().indexOf(this.filterTermValue) - b.name.toLowerCase().indexOf(this.filterTermValue)
  );
...