JS массив объектов найти по ключу и объединить - PullRequest
0 голосов
/ 03 октября 2018

Иметь массив с объектами, иметь объекты поиска по tenant_question_id & tenant_option_id и должен объединять other1 & other2 (который не имеет "") и иметь уникальный объект в массиве

Ввод

[
  {
    tenant_question_id: "3",
    tenant_option_id: "22",
    other1: "$20,000.00",
    other2: ""
  },
  {
    tenant_question_id: "3",
    tenant_option_id: "22",
    other1: "",
    other2: "on"
  },
  {
    tenant_question_id: "3",
    tenant_option_id: "23",
    other1: "",
    other2: ""
  },
  {
    tenant_question_id: "3",
    tenant_option_id: "23",
    other1: "$ 500.00",
    other2: ""
  }
]

Ожидаемый результат

[
  {
    tenant_question_id: "3",
    tenant_option_id: "22",
    other1: "$20,000.00",
    other2: "on"
  },
  {
    tenant_question_id: "3",
    tenant_option_id: "23",
    other1: "$ 500.00",
    other2: ""
  }
]

Попытка _.filter, _.omit не может его найти.Есть идеи?

Ответы [ 4 ]

0 голосов
/ 03 октября 2018

Я только что сделал это, он возвращает именно тот результат, который вы хотели.

var data = [{
    tenant_question_id: "3",
    tenant_option_id: "22",
    other1: "$20,000.00",
    other2: ""
  },
  {
    tenant_question_id: "3",
    tenant_option_id: "22",
    other1: "",
    other2: "on"
  },
  {
    tenant_question_id: "3",
    tenant_option_id: "23",
    other1: "",
    other2: ""
  },
  {
    tenant_question_id: "3",
    tenant_option_id: "23",
    other1: "$ 500.00",
    other2: ""
  }
];

data = data.map(function(item, index, arr) {

  // We remove the current mapped item from arr(self)
  // So we can search within an arr that doesn't contain our "item" at the "index" position
  arr.splice(index, 1);

  if (item.other2 === '') {

    var weFoundAnother = arr.find(function(elem, idx) {
      return elem.tenant_question_id === item.tenant_question_id &&
        elem.tenant_option_id === item.tenant_option_id &&
        elem.other2.length;
    });

    if (weFoundAnother !== undefined) {

      // We found our element and now we'll remove this too from "arr"
      // Let's get "weFoundAnother" index first using 
      //  -> arr.indexOf(weFoundAnother)
      // Then we can remove it from "arr" because it is used now.
      arr.splice(arr.indexOf(weFoundAnother), 1);

      item.other2 = weFoundAnother.other2;

    }

  }

  return item;

  // Now we'll filter the empty slots ( items that we removed )
  // And that's it

}).filter(function(i) {
  return i !== undefined
})

console.clear();
console.log(data);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
0 голосов
/ 03 октября 2018

Следующий код должен выполнить трюк:

const mergedData = input.reduce((resultArray, tenantData) => {
  const index = resultArray.findIndex(entry => entry.tenant_question_id === tenantData.tenant_question_id && entry.tenant_option_id === tenantData.tenant_option_id);
  if (index!==-1) {
    const existingData = resultArray[index];
    if (!existingData.other1) {
      existingData.other1 = tenantData.other1;
    }
    if (!existingData.other2) {
      existingData.other2 = tenantData.other2;
    }
  } else {
    resultArray.push(tenantData);
  }
  return resultArray;
}, []);

В основном итерация по массиву и постепенное заполнение результирующего массива.Для каждого элемента проверьте, существует ли элемент с tenant_question_id и tenant_option_id, если он существует, мы перезапишем other1 и other2, если они имеют значение фальси ("") в существующем объекте.Если он не существует, мы выдвигаем текущий объект.

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

0 голосов
/ 03 октября 2018

С некоторой помощью функциональных библиотек crocks и ramda вы можете сделать это в более или менее декларативном стиле.

const { groupWith, eqProps, equals } = R
const { assign, map, reduce, compose } = crocks

const data = [
  {tenant_question_id: "3", tenant_option_id: "22", other1: "$ 20,000.00", other2: ""},
  {tenant_question_id: "3", tenant_option_id: "22", other1: "", other2: "on"},
  {tenant_question_id: "3", tenant_option_id: "23", other1: "", other2: ""},
  {tenant_question_id: "3", tenant_option_id: "23", other1: "$ 500.00", other2: ""}
];

const expected = [
  {tenant_question_id: "3", tenant_option_id: "22", other1: "$ 20,000.00", other2: "on"},
  {tenant_question_id: "3", tenant_option_id: "23", other1: "$ 500.00", other2: ""}
];

// This could be composed of entries, fromEntries, and filter,
// but this approach saves an iteration.
const stripFalsyValues = t =>
  Object.entries(t)
    .reduce((a, [k, v]) => ({...a, ...(v && {[k]: v})}), {})

const mergeAll = reduce(assign, {})

const isSameTenantOptionId = eqProps('tenant_option_id')

const groupByTenantOptionId = groupWith(isSameTenantOptionId)

const mergeTenants = compose(
  map(mergeAll),
  groupByTenantOptionId,
  map(stripFalsyValues)
)

const result = mergeTenants(data)


console.log({expected, result})
<script src="https://unpkg.com/crocks/dist/crocks.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js" integrity="sha256-YN22NHB7zs5+LjcHWgk3zL0s+CRnzCQzDOFnndmUamY=" crossorigin="anonymous"></script>

Обратите внимание, что в отношении отсутствующего other2: "" во втором объекте результата это может быть обработано на границе со свойствами по умолчанию для целей пользовательского интерфейса.Если вам абсолютно необходимо передать пустую строку, вы можете составить вместе assignWhen = when(undefinedOption2, assign({option2: ""})

0 голосов
/ 03 октября 2018

Создать индекс по ключу tenant_question_id и tenant_option_id и объединить соответствующие свойства на каждой итерации.Затем просто возьмите значения индекса и все готово.

let tenants = [{
  tenant_question_id: "3",
  tenant_option_id: "22",
  other1: "$ 20,000.00",
  other2: ""
}, {
  tenant_question_id: "3",
  tenant_option_id: "22",
  other1: "",
  other2: "on"
}, {
  tenant_question_id: "3",
  tenant_option_id: "23",
  other1: "",
  other2: ""
}, {
  tenant_question_id: "3",
  tenant_option_id: "23",
  other1: "$ 500.00",
  other2: ""
}];
let result = {};

for (item of tenants) {
  let key = item.tenant_question_id + ";" + item.tenant_option_id;
  if (key in result) {
    const properties = ["other1", "other2"];
    for (property of properties) {
      if (item[property]) {
        result[key][property] = item[property];
      }
    }
  } else {
    result[key] = Object.assign(item);
  }
}
result = Object.values(result);

console.log(result);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...