Поиск уникальных объектов внутри родительского массива объектов

#javascript #arrays #object #duplicates

#javascript #массивы #объект #дубликаты

Вопрос:

У меня есть массив объектов, подобных приведенному ниже:

 const myArray = [
    {
      main_query: "query-1",
      conditions: [
        {
          field: "branch_primary",
          query: "1"
        },
        {
          field: "web_domain",
          query: "google.de"
        }
      ]
    },
    {
      main_query: "query-1",
      conditions: [
        {
          field: "branch_primary",
          query: "2"
        },
        {
          field: "web_domain",
          query: "google.de"
        }
      ]
    },
    {
      main_query: "query-1",
      conditions: [
        {
          field: "branch_primary",
          query: "3"
        },
        {
          field: "web_domain",
          query: "google.de"
        }
      ]
    }
];
  

Пожалуйста, обратите внимание, что у меня есть вложенный массив объектов с ключом: условия внутри каждого моего родительского объекта. Все три основных родительских объекта имеют ключи: main_query и conditions.

main_query имеет значение string, и они одинаковы для всех трех основных объектов.

условия снова представляют собой массив объектов с ключами: поле и запрос

Все три основных объекта имеют одинаковые пары ключ-значение / выглядят одинаково, за исключением значения ключа запроса для поля: «primary_branch», которое равно 1, 2, 3 соответственно.

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

 const keys = ["main_query", "conditions"];
const filtered = myArray.filter(
  ((s) => (o) =>
    ((k) => !s.has(k) amp;amp; s.add(k))(keys.map((i) => o[i]).join("|")))(
    new Set()
  )
);
const result = filtered.map((o) => Object.fromEntries(keys.map((k) => [k, o[k]])));

console.log(result);
  

К сожалению, результат, который я получаю, приведен ниже:

 {
  main_query: "query-1",
  conditions: [{
      field: "branch_primary",
      query: "1"
    },
    {
      field: "web_domain",
      query: "google.de"
    }
  ]
}
  

Но я ожидаю, что все три объекта будут отображаться в консоли, потому что поле «primary_branch» имеет разные значения запроса.

Ожидаемый результат должен быть:

 {
  main_query: "query-1",
  conditions: [{
      field: "branch_primary",
      query: "1"
    },
    {
      field: "web_domain",
      query: "google.de"
    }
  ]
}, {
  main_query: "query-1",
  conditions: [{
      field: "branch_primary",
      query: "2"
    },
    {
      field: "web_domain",
      query: "google.de"
    }
  ]
}, {
  main_query: "query-1",
  conditions: [{
      field: "branch_primary",
      query: "3"
    },
    {
      field: "web_domain",
      query: "google.de"
    }
  ]
}
  

Вот моя ссылка на codepen, касающаяся этого кода.

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

1. Для тех, кого еще смущает этот код, он использует концепцию, называемую каррированием

Ответ №1:

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

 const stringify = ({main_query, condtions}) =>
    JSON.stringify([
        main_query, 
        ...condtions.map(({field, query}) => [field, query])
                    .sort((a, b) => a[0].localeCompare(b[0]))
    ]);

let result = Array.from(new Map(myArray.map(query => [stringify(query), query])).values());
  

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

1. вау, это выглядит как потрясающее решение @trincot…. позвольте мне попробовать и попытаться понять ваш код .. я свяжусь с вами как можно скорее после его тестирования .. большое спасибо

2. итак, это работает как шарм .. большое спасибо, я принимаю ваш ответ .. приветствия

Ответ №2:

Намного сложнее, чем другой ответ, но здесь это мое рабочее решение:

 function uniqueItems(arr) {
    var uniqueArr = [], uniqueArrStrings = [];
    arr.forEach(el => {
        if(!uniqueArrStrings.includes(JSON.parse(JSON.stringify(el).toString()).toString())) {
            uniqueArrStrings.push(JSON.parse(JSON.stringify(el).toString()).toString());
            uniqueArr.push(JSON.parse(JSON.stringify(el).toString()));
        };
    });
    return uniqueArr;
};
  

Ответ №3:

Это даст уникальный массив объектов

 for(var myObj of myArray) {
    var set = new Set();
    for(var i = 0; i < myObj.conditions.length; i  ) {
        var condition = myObj.conditions[i];
        var strCond = JSON.stringify(condition);
        if(set.has(strCond)) {
            myObj.conditions.splice(i, 1);
            i--;
            continue;
        }
        set.add(strCond);
    }
}
console.log(myArray)
  

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

1. попробуйте свой код const myArray = [{conditions:[1]},{conditions:[1]}] , он печатает исходный массив…

2. @arVi, я протестировал это, извините, к сожалению, это не работает.. вы можете попробовать мой codepen и проверить себя .. извините

Ответ №4:

Создайте функцию, которая принимает на вход массив с объектами и выдает на выходе другой массив, но только с уникальными объектами внутри (работает с любым типом значения или объекта).

 function uniqueItems(arr) {
    let uniqueArr = [];
    arr.forEach(el => {
        if (!uniqueArr.includes(el)) {
            uniqueArr.push(el);
        };
    });
    return uniqueArr;
};
  

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

1. Операция посвящена массиву объектов. Попробуйте свой код uniqueItems([{a:1},{a:1}]) . Оба объекта «уникальны» в том смысле, что они просто разные объекты, но, вероятно, не то, что требует OP.. Что еще более важно, ваш ответ не содержит информации о том, как решить проблему OP

2. извини, чувак, это немного сложнее, чем ты думаешь @smunteanu

3. Я бы понизил свой собственный ответ, если бы мог facepalm

4. @smunteanu просто учись на этом, это очень хороший результат 🙂