Как сортировать и соединять по ключам в Javascript

Прежде всего, я новичок в базе данных Nosql, но для моего приложения я впервые попробовал использовать firebase. Я создаю приложение о чем-то, и в этом приложении у меня есть кандидаты, которые вносят определенную сумму денег каждый месяц в определенную дату. чтобы сохранить это в моем firebase Firestore, я создал транзакцию имени коллекции, и в ней для пользователя я сохраняю все его транзакции.

transaction2018(collection) -> userId1(collection) -> { ....result1 }
                        -> userId2(collection) -> { ....result2 }
                     -> userId3(collection) -> { ....result3 }

transaction2019(collection) -> userId1(collection) -> { ....result1 }
                         -> userId2(collection) -> { ....result2 }
                         -> userId3(collection) -> { ....result3 }

That is the reason i have designed like that so for every user i can get all his transaction in one object One more thing in my resuly object amount_2,data_2 two is actually month(feb) and if i dont do this that I'll have to go deeper something like :

transaction2018 -> userId1 -> January -> {amount,date.....}
                        -> February
                        .....

which is not actually a good practice in Nosql databases.

Я использую базу данных NoSql, и результат, который я получаю, имеет следующий формат: Как я могу преобразовать это в желаемый формат после извлечения данных:

let result = {
  amount_2       : "1000",
  amount_3       : "1200",
  date_2         : "15/2/2019",
  date_3         : "15/3/2019",
  modeOfPayment_2: "Cash",
  modeOfPayment_3: "Cash",
  note_2         : "áßðáßðáßð↵áß",
  note_3         : "",
  refNum_2       : "11111",
  refNum_3       : "Fffff",
  submittedByID_2: "T62tgJcjieSJsAEJT69VfpRc5Mw2",
  submittedByID_3: "T62tgJcjieSJ"
};

Я хочу что-то вроде:

var output = [
  {
    amount2,
    date2,
    ....
  },
  {
   amount3,
   date3,
   ...... 
  }
]

Вы читали о том, как форматировать свой код здесь, на SO?

Dexygen 16.02.2019 09:48

Прежде всего, вы должны лучше спроектировать базу данных — это не то, как предполагается использовать базу данных.

JJJ 16.02.2019 09:51

сейчас хорошо выглядит?

Eddy sapata 16.02.2019 09:51

@JJJ я использую базу данных NoSql, уже упомянутую ранее

Eddy sapata 16.02.2019 09:52

@Eddysapata рассмотрите возможность обновления вашего вопроса, чтобы показать нам, что вы уже пытались сделать.

Dacre Denny 16.02.2019 09:53

Плохо, но это неправильный формат даже для базы данных NoSQL. Каждый пункт должен быть в своем (под)документе, а не втиснут в один.

JJJ 16.02.2019 09:54

@Eddysapata Если вы прочитаете Как спросить, вы обнаружите, что пользователь, публикующий вопрос, должен провести надлежащее исследование и продемонстрировать свои собственные усилия, а вы явно этого не сделали.

Asons 16.02.2019 09:54

@JJJ Я отредактировал вопрос, как вы получите ответ. :)

Eddy sapata 16.02.2019 10:09

@DacreDenny Я могу повторить это и получить данные в соответствии со своими потребностями, но я искал наиболее красноречивый способ. P.S-> И именно поэтому я не пробовал в первую очередь!

Eddy sapata 16.02.2019 10:11

Это должно решаться не в JavaScript, а в структуре вашей базы данных и запросе.

trincot 16.02.2019 10:24
«Я разработал так, чтобы для каждого пользователя я мог получить всю его транзакцию в одном объекте» — но теперь вы все равно хотите разделить его на разные объекты после получения одного объекта? Это не имеет никакого смысла. Сделайте так, чтобы структура базы данных соответствовала желаемому результату.
JJJ 16.02.2019 10:24
"что на самом деле не является хорошей практикой в ​​базах данных Nosql" — да. Сохраняйте даты как фактические даты, а не строки, и запрашивайте базу данных с диапазоном дат. Вы сразу получите желаемый конечный результат.
JJJ 16.02.2019 10:25
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
12
46
4

Ответы 4

К настоящему моменту кажется, что вы хотите сгруппировать поля в объекты в зависимости от чисел в хвосте каждого индекса.

const result = [];
_.each(inputObject, (key, value) => {
    const [,keyName, indexPart] = key.match(/^(.*)_(\d+)$/);
    result[indexPart] = result[indexPart] || {};
    result[indexPart][keyName] = value;
});

Вы можете сделать это в простом JavaScript, используя Object.entries и Array.reduce для создания промежуточного словаря, ключами которого являются цифры в конце ваших ключей. Это сгруппирует ваши пары ключ/значение по этой цифре, затем вы сможете получить результат, взяв значения этого словаря, используя Object.values.

С помощью key.match(/(\d+)$/) вы можете извлечь число в конце ваших ключей и использовать его в качестве ключа для промежуточного словаря.

Используя положительное регулярное выражение /_(?=\d)/, вы можете удалить подчеркивание, если оно предшествует цифре в конце ваших ключей, чтобы получить новые имена ключей.

const data = {
  amount_2       : "1000",
  amount_3       : "1200",
  date_2         : "15/2/2019",
  date_3         : "15/3/2019",
  modeOfPayment_2: "Cash",
  modeOfPayment_3: "Cash",
  note_2         : "áßðáßðáßð↵áß",
  note_3         : "",
  refNum_2       : "11111",
  refNum_3       : "Fffff",
  submittedByID_2: "T62tgJcjieSJsAEJT69VfpRc5Mw2",
  submittedByID_3: "T62tgJcjieSJ"
};

const result = Object.values(Object.entries(data).reduce((dict, [key, val]) => {
  // reduce is called for each key/value pair in your input data
  // here we add the key/value pair in the proper entry based
  // on the number extracted at the end
  const num = key.match(/(\d+)$/); // get number at end of key
  const newKey = key.replace(/_(?=\d)/, ''); // remove underscore before digit
  dict[num] = dict[num] || {}; // create a default entry if needed
  dict[num][newKey] = val; // set value for the new key
  return dict; // return intermediate dictionary
}, {}));

console.info(result);

Вы можете рассмотреть возможность использования одного регулярного выражения для извлечения имени и номера из каждой клавиши входного (results) объекта с помощью следующего:

const [, name, number] =  key.match(/^(.*)_(\d+)$/);

Где key — текущий ключ result, который повторяется. Это единственное регулярное выражение вернет name и number из key в соответствии с заданным вами форматом. Полное решение может быть достигнуто независимо от lodash, как показано ниже:

let result = {
  amount_2       : "1000",
  amount_3       : "1200",
  date_2         : "15/2/2019",
  date_3         : "15/3/2019",
  modeOfPayment_2: "Cash",
  modeOfPayment_3: "Cash",
  note_2         : "áßðáßðáßð↵áß",
  note_3         : "",
  refNum_2       : "11111",
  refNum_3       : "Fffff",
  submittedByID_2: "T62tgJcjieSJsAEJT69VfpRc5Mw2",
  submittedByID_3: "T62tgJcjieSJ"
};

/* Compose Object.values() and Object.entries() with reduce. Here we get
the key/value pairs (entries) of the input "results" object, and reduce
the key/values into an object of nsted objects of key/values grouped by 
number.
We then aquire an array of the grouped objects using Object.values() */
const groupedResult = Object.values(Object.entries(result).reduce((output, [key,value]) => {
   
  /* Extract key and number parts of current entry of result object */
  const [, name, number] =  key.match(/^(.*)_(\d+)$/);
  
  /* Fetch or insert (empty) object for the number corresponding to
  this entries key */
  const group = output[ number ] = output[ number ] || {}
  
  /* Compose a key with number suffix and insert value into group
  object for composed key */
  group[ `${name}${ number }` ] = value;
  
  /* Return current output object for next iteration of reduce */
  return output;

}, {}))

console.info(groupedResult);

Вы можете создать функцию с помощью _.flow(), которая разбивает объект на массив записей (_.pairs()), группирует по числу в ключе, а затем сопоставляет результат обратно с объектом (_.fromPairs) и обновляет ключи (_.mapKeys()).

const { flow, toPairs, groupBy, partialRight: pr, map, fromPairs, mapKeys } = _;

const pattern = /_+(\d+)$/;
const getKeyId = ([k]) => (k.match(pattern) || [''])[0];

const fn = flow(
  toPairs, // convert to entries
  pr(groupBy, getKeyId), // group by the number in the key
  pr(map, flow( // map back to object
    fromPairs, // combine the entries in the group
    pr(mapKeys, (v, k) => k.replace(pattern, '$1')) // update the keys
  ))
);

const data = {
  amount_2       : "1000",
  amount_3       : "1200",
  date_2         : "15/2/2019",
  date_3         : "15/3/2019",
  modeOfPayment_2: "Cash",
  modeOfPayment_3: "Cash",
  note_2         : "áßðáßðáßð↵áß",
  note_3         : "",
  refNum_2       : "11111",
  refNum_3       : "Fffff",
  submittedByID_2: "T62tgJcjieSJsAEJT69VfpRc5Mw2",
  submittedByID_3: "T62tgJcjieSJ"
};

const result = fn(data);

console.info(result);
<script src = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

И то же решение с использованием Лодаш/fp:

const { flow, toPairs, groupBy, map, fromPairs, mapKeys, replace } = _;

const pattern = /_+(\d+)$/;
const getKeyId = ([k]) => (k.match(pattern) || [''])[0];

const fn = flow(
  toPairs, // convert to entries
  groupBy(getKeyId), // group by the number in the key
  map(flow( // map back to object
    fromPairs, // combine the entries in the group
    mapKeys(replace(pattern, '$1')) // update the keys
  ))
);

const data = {
  amount_2       : "1000",
  amount_3       : "1200",
  date_2         : "15/2/2019",
  date_3         : "15/3/2019",
  modeOfPayment_2: "Cash",
  modeOfPayment_3: "Cash",
  note_2         : "áßðáßðáßð↵áß",
  note_3         : "",
  refNum_2       : "11111",
  refNum_3       : "Fffff",
  submittedByID_2: "T62tgJcjieSJsAEJT69VfpRc5Mw2",
  submittedByID_3: "T62tgJcjieSJ"
};

const result = fn(data);

console.info(result);
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

Другие вопросы по теме