Отфильтруйте данные, чтобы они соответствовали списку ключей

#javascript #node.js #algorithm #data-structures

#язык JavaScript #node.js #алгоритм #структуры данных

Вопрос:

У меня есть код, который будет фильтровать данные в соответствии с указанным набором ключей. До сих пор мой код обрабатывает, являются ли передаваемые данные массивом или объектом определенного типа. Например, объект автомобиля или массив объектов автомобиля, а ключевым списком будут атрибуты автомобиля. Тем не менее, я только что получил новый набор данных, и мне интересно, как лучше всего с ним обращаться. Вот мой код до сих пор (не беспокойтесь слишком сильно о проверке моего массива/объекта, у меня есть пользовательские функции, которые выполняют гораздо больше проверок)

 const goodDataObject = {  "make": "toyota",  "model": "rav4",  "color": "white"  "mileage": "10000",  "engine": "hybrid" };  const goodDataArray = [  {  "make": "toyota",  "model": "rav4",  "color": "white"  "mileage": "10000",  "engine": "hybrid"  },  {  "make": "chevrolet",  "model": "cruze",  "color": "black"  "mileage": "20000",  "engine": "gas"  } ]  const badDataObject = {  "dealer": "John Does Cars",  "factory": "Michigan",  "cars": [  {  "make": "toyota",  "model": "rav4",  "color": "white"  "mileage": "10000",  "engine": "hybrid"  },  {  "make": "chevrolet",  "model": "cruze",  "color": "black"  "mileage": "20000",  "engine": "gas"  }  ] }   // --gt;gt; results from goodDataObject: {  "make": "toyota",  "model": "rav4" }   // --gt;gt; results from goodDataArray: [  {  "make": "toyota",  "model": "rav4"  },  {  "make": "chevrolet",  "model": "cruze"  } ]   // --gt;gt; results I WANT from badDataObject: {  "dealer": "John Does Cars",  "factory": "Michigan",  "cars": [  {  "make": "toyota",  "model": "rav4"  },  {  "make": "chevrolet",  "model": "cruze"  }  ] }  

Вот мой текущий код, вызываемый с помощью ключей ["make", "model"] .

 function filterData(data, keys) {  let filtered = null;    if (typeof data === 'object') {  for (let x of keys) {  filtered[x] = data[x]  }  } else if (Array.isArray(data)) {  filtered = [];  for (let y of data) {  let filteredObject = {};  for (let key of keys) {  filteredObject[key] = y[key];  }  filtered.push(filteredObject);  }  }  return filtered; }  

Мне нужно обработать объект badDataObject, и я думал о рекурсивном варианте, но пока это не увенчалось успехом, поэтому я не могу там много публиковать

Обновление: Ключи являются примерами, но я должен справиться со всеми. Кроме того, примером может служить объект badDataObject. cars может быть vans или trucks и т. Д.

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

1. Как вы различаете dealer то , с чем вы не справляетесь, и cars то , что вы делаете? Что делать, если в dealer собственности был объект с model ребенком? Кроме того, могут ли объекты, которые вы хотите спроектировать, быть вложены произвольно глубоко? Если да, то как вы решаете, на каких уровнях проводить проекцию?

Ответ №1:

Если вы уверены, что badDataObject будет содержать ключ «автомобили», то вам следует просто отфильтровать, извлекая только этот ключ.

В противном случае вы можете написать рекурсивную функцию, которая определяет, содержит ли какой-либо ключ данные(массив или объект), содержащие нужные ключи, но я думаю, что это было бы излишним и сложным в управлении.

Ответ №2:

Я думаю, что ваши требования не совсем ясны, как я уже упоминал в комментариях. Но, угадав их, мы можем написать что-то, что ищет подобъекты, обладающие ключевыми свойствами, которые мы ищем, а затем сохранить только их, сохранив все, где отсутствует какой-либо из этих ключей. Это может выглядеть так:

 const map = (fn) =gt; (o) =gt;   Array .isArray (o)  ? o .map (fn)  : Object .fromEntries (Object .entries (o) .map (([k, v]) =gt; [k, fn (v)]))  const select = (ks) =gt; (o) =gt;   Object (o) === o  ? ks .every (k =gt; k in o)  ? Object .fromEntries (ks .map (k =gt; [k, o [k]]))  : map (select (ks)) (o)  : o  const goodDataObject = {make: "toyota", model: "rav4", color: "white", mileage: "10000", engine: "hybrid"} const goodDataArray = [{make: "toyota", model: "rav4", color: "white", mileage: "10000", engine: "hybrid"}, {make: "chevrolet", model: "cruze", color: "black", mileage: "20000", engine: "gas"}] const badDataObject = {dealer: "John Does Cars", factory: "Michigan", cars: [{make: "toyota", model: "rav4", color: "white", mileage: "10000", engine: "hybrid"}, {make: "chevrolet", model: "cruze", color: "black", mileage: "20000", engine: "gas"}]}  console .log ('goodDataObject:', select (['make', 'model']) (goodDataObject)) console .log ('goodDataArray:', select (['make', 'model']) (goodDataArray)) console .log ('badDataObject:', select (['make', 'model']) (badDataObject)) 
 .as-console-wrapper {max-height: 100% !important; top: 0} 

Вот map вспомогательная функция, которая вызывает Array.prototype.map массивы и делает что-то довольно эквивалентное для объектов. ( map (n =gt; n ** 2) ({a: 1, b: 2, c: 3}) возвращается {a: 1, b: 4, c: 9} .)

Наша основная функция select принимает массив целевых ключей и возвращает функцию, которая принимает объект, проверяет, есть ли у него все целевые ключи. Если их там нет, он возвращается к своим детям. Если это так, он извлекает только эти ключи. И если это вообще не объект, он возвращает его в целости и сохранности.

Вы можете увидеть поведение более сложного объекта, такого как этот:

 {  company: "Acme Corp",   office: "Chicago",   companyCars: [  {make: "toyota", model: "rav4", color: "white", mileage: "10000", engine: "hybrid"},   {make: "chevrolet", model: "cruze", color: "black", mileage: "20000", engine: "gas"}  ],  departments: {  marketing: {  director: 'Susan',  car: {make: "dodge", model: "neon", color: "red", mileage: "10000", engine: "gas"},   },  sales: {  local: {  manager: 'Peter',  fleet: [  {make: "toyota", model: "rav4", color: "blue", mileage: "30000", engine: "hybrid"},   {make: "chevrolet", model: "cruze", color: "green", mileage: "50000", engine: "gas"}  ]  },  state: {  manager: 'Edmond'  },  national: {  manager: 'Lucy',  marketingVehicle: {make: "Prevost", model: "X3-45", engineHours: "900", paintjob: "purple logo"},   }  }  } }  

Он вернет это:

 {  company: "Acme Corp",  office: "Chicago",  companyCars: [  {make: "toyota", model: "rav4"},  {make: "chevrolet", model: "cruze"}  ],  departments: {  marketing: {  director: "Susan",  car: {make: "dodge", model: "neon"}  },  sales: {  local: {  manager: "Peter",  fleet: [  {make: "toyota", model: "rav4"},  {make: "chevrolet", model: "cruze"}  ]  },  state: {  manager: "Edmond"  },  national: {  manager: "Lucy",  marketingVehicle: {make: "Prevost", model: "X3-45"}  }  }  } }  

Ответ №3:

Должно быть легко сделать с помощью Array.map() .

Я обновил функцию, так что теперь она также принимает объект, описывающий, какие данные вам нужны.

 const badDataObject = {  "dealer": "John Does Cars",  "factory": "Michigan",  "cars": [{  "make": "toyota",  "model": "rav4",  "color": "white",  "mileage": "10000",  "engine": "hybrid"  },  {  "make": "chevrolet",  "model": "cruze",  "color": "black",  "mileage": "20000",  "engine": "gas"  }  ] };  function goodDataObject(data, target) {  for (const prop in target){  data[prop] = data[prop].reduce((acc, item) =gt; {  const obj = {};  for(const key of target[prop]){  if(key in item) obj[key] = item[key];  }  acc.push(obj);  return acc;  }, []);  }  return data; }  console.log(goodDataObject(  badDataObject,   { cars: [ "model", "make"]} )) 

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

1. Я обновил, чтобы упомянуть, что мои ключи и объект badDataObject являются примерами. Мне нужно обработать все возможные ключи, и машины-это всего лишь пример. Извините, что не совсем ясно выразился

2. @johnny_mac Я обновил код, так что вы можете выбрать нужные вам данные.