Фильтрация данных локального хранилища по полю и вывод их на страницу

#javascript #jquery #local-storage

#javascript #jquery #локальное хранилище

Вопрос:

Я пытаюсь понять, как чего-то добиться. У меня есть тип карты, на которой вы можете щелкнуть по стране и ввести некоторые данные. Когда данные отправляются, я сохраняю их в локальном хранилище

 $('#question-form').on('submit', function(e){
    e.preventDefault();

    let country = $('#hidden-input').val();
    let questionOne = $('#questionOne').val();
    let questionTwo = $('#questionTwo').val();
    
    let clientObj = {
        country : country,
        questionOne : questionOne,
        questionTwo: questionTwo
    };
    
    let clientsArr = [];

    if(!localStorage.getItem('Countries')) {
        clientsArr.push(clientObj);
        localStorage.setItem('Countries', JSON.stringify(clientsArr));
    } else {
        clientsArr = JSON.parse(localStorage.getItem('Countries'));
        clientsArr.push(clientObj);
        localStorage.setItem('Countries', JSON.stringify(clientsArr));
    }

    $('#myModal').modal('hide');
});
  

Через некоторое время мое локальное хранилище заполняется данными, которые принимают следующую форму

 [{country: "United Kingdom", questionOne: "test", questionTwo: "test"},…]
    0: {country: "United Kingdom", questionOne: "test", questionTwo: "test"}
    1: {country: "Ireland", questionOne: "test 2", questionTwo: "test 2"}
    2: {country: "Iran", questionOne: "Test 3", questionTwo: "Test 3"}
    3: {country: "United Kingdom", questionOne: "Test 4", questionTwo: "Test 4"}
  

То, что я пытаюсь сделать, это отобразить эти результаты. Итак, на моей странице у меня есть несколько заполнителей

 <div id="display">
    <div id="country-name"></div>
    <div class="question-one-data"></div>
    <div class="question-two-data"></div>
</div>
  

Затем я дошел до этого момента

 if (!localStorage.getItem('Countries')) {
    $('#display').html('<p>No results to display</p>');
} else {
    console.log(JSON.stringify(localStorage.getItem('Countries')))
}
  

Поэтому, если данных нет, это сообщит пользователю. Это в другом, я немного застрял. Теперь отображение данных не является проблемой. С чем я борюсь, так это с фильтрацией. Поэтому я хочу, чтобы для страны был установлен заполнитель имени страны,
однако он должен отображать страну только один раз. Поэтому мне, по сути, нужно фильтровать мои результаты по странам. В моем примере вы можете видеть, что для Соединенного Королевства было две записи, поэтому результат, который я ищу, это

 <div id="display">
    <div id="country-name">United Kingdom</div>
    <div class="question-one-data">test</div>
    <div class="question-two-data">test</div>
    <hr>
    <div class="question-one-data">Test 4</div>
    <div class="question-two-data">Test 4</div>
    <hr>
    <div id="country-name">Ireland</div>
    <div class="question-one-data">test 2</div>
    <div class="question-two-data">test 2</div>
    ...
</div>
  

Как бы мне отфильтровать свои данные по названию страны, а затем получить структуру, как показано выше?

Спасибо

Комментарии:

1. Вы имеете в виду, что хотите исправить свои данные, чтобы каждый объект countryName с определенным значением встречался в массиве только один раз?

Ответ №1:

Допустим, у вас есть ваши данные в переменной с именем answers . Вы можете создать список всех уникальных названий стран с помощью:

 const countries = Array.from(new Set(answers.map(a => a.country)))
  

Затем вы можете изменить свои данные и сохранить все ответы для данной страны в новом массиве:

 const countriesWithAnswers = countries.map(countryName => ({
  name: countryName,
  answers: answers
    .filter(answer => answer.country === countryName)
    .map(({ questionOne, questionTwo }) => ({ questionOne, questionTwo }))
}))
  

Чтобы отобразить данные, вы можете выполнить итерацию по answers массиву для каждого элемента countriesWithAnswers .

Ответ №2:

Если я правильно понимаю вашу задачу, вот мое предполагаемое решение

Сначала вам нужно отсортировать массив по названию страны:

 countriesArray = [
  {country: "United Kingdom", questionOne: "test", questionTwo: "test"}, 
  {country: "Ireland", questionOne: "test 2", questionTwo: "test 2"}, 
  {country: "Iran", questionOne: "Test 3", questionTwo: "Test 3"}, 
  {country: "United Kingdom", questionOne: "Test 4", questionTwo: "Test 4"}
  ...
]

countriesArray.sort((a, b) => {
    if (a.country < b.country) return -1
    if (a.country > b.country) return 1
    return 0
})
  

Затем вы можете выполнить итерацию по нему, чтобы собрать все данные, определенные для конкретного названия страны:

 let currentCountry
const results = {}

for (const item of countriesArray) {
    const { country, questionOne, questionTwo } = item;

    if (currentCountry === undefined || currentCountry !== country) {
        currentCountry = country
    }

    if (!results[currentCountry]) {
        results[currentCountry] = []
    }

    results[currentCountry].push({
        questionOne,
        questionTwo,
    })
}
  

После этого вы можете снова выполнить итерацию по нему и отобразить некоторый HTML.
Надеюсь, это решит вашу проблему 👌

Ответ №3:

ваш исходный массив стран

 let countries =[
  {country: "United Kingdom", questionOne: "test", questionTwo: "test"},
  {country: "Ireland", questionOne: "test 2", questionTwo: "test 2"},
  {country: "Iran", questionOne: "Test 3", questionTwo: "Test 3"},
  {country: "United Kingdom", questionOne: "Test 4", questionTwo: "Test 4"}
];
  

объявите переменную с именем sortedCountries . выполните итерацию по массиву стран и для каждой страны проверьте, не существует ли название страны в отсортированном массиве. затем вставьте его в отсортированный массив.

 let sortedCountries = [];

countries.forEach(country => {
  if (!sortedCountries.some(el => el.country === country.country)) {
    sorted.push(country)
  };
})
  

Ответ №4:

Создайте список уникальных стран с помощью Set объекта. Этот объект может содержать коллекцию значений с условием, что каждое значение уникально, что упрощает фильтрацию дубликатов. Превращение набора обратно в массив позволяет использовать его для дальнейшего зацикливания и манипулирования.

Затем перебирайте каждое название страны с Array.prototype.map() помощью и используйте Array.prototype.find() , чтобы найти первое вхождение названия страны в массиве, с которым вы работаете. Это создаст новый массив с объектами, которые ранее не встречались.

 const questions = [
  {
    country: "United Kingdom",
    questionOne: "test",
    questionTwo: "test"
  },
  {
    country: "Ireland",
    questionOne: "test 2",
    questionTwo: "test 2"
  },
  {
    country: "Iran",
    questionOne: "Test 3",
    questionTwo: "Test 3"
  },
  {
    country: "United Kingdom",
    questionOne: "Test 4",
    questionTwo: "Test 4"
  }
];

const filterQuestions = questions => {
  const uniqueCountries = Array.from(new Set(
    questions.map(({ country }) => country))
  );
  return uniqueCountries.map(country =>
    questions.find(question => question.country === country)
  );
}

const uniqueQuestions = filterQuestions(questions);

console.log(uniqueQuestions);