Найдите, является ли объект подмножеством другого объекта в javascript

мне нужна функция isSubset, которая при задании двух объектов сравнивает свои значения и говорит, является ли один объект подмножеством другого.

object1 = { pickUpLocation : {city : 'Hyderabad', state: 'Telangana' }};
object2 = { dist : 322, pickUpLocation:  {city : 'Hyderabad', state: 'Telangana' }};
isSubset(object1, object2); //should return true
object3 = { pickUpLocation : {city : 'Chennai', state: 'Telangana' }}
object4 = { dist : 322, pickUpLocation: {city : 'Hyderabad', state: 'Telangana' }}
isSubset(object3, object4) //should return false as city's value is different

8 ответов


На Английском Языке:

здесь некоторые ключ в object2 что satisifies условии, что есть глубокий равнойity между его значением и object1?

написать это:

_.some(                       // Is there some key
  object2,                    // in object2
  function(val, key) {             // which satisfies the condition that
    return _.isEqual(         // there is deep equality between
      val,                    // its value and
      object1[key]                 // object1?
    );
  }
);

в более краткой форме:

_.some(object2, function(val, key) { return _.isEqual(val, object1[key]); })

в ES6:

_.some(object2, (val, key) => _.isEqual(val, object1[key]))

мое предложение-прочитать лодаш docs и узнать все API, или, по крайней мере основные из них. Например, это проблема будет очень трудно решить самостоятельно, если вы не знаете о важных подпрограмм, таких как _.some и _.isEqual. С другой стороны, если вы их знаете, то это довольно тривиально.


вы можете попробовать использовать isSubset пакета.

Это правда

isSubset(
  { dist : 322, pickUpLocation:  {city : 'Hyderabad', state: 'Telangana' }},
  { pickUpLocation : {city : 'Hyderabad', state: 'Telangana' }}
);

Это ложь

isSubset(
  { dist : 322, pickUpLocation:  {city : 'Hyderabad', state: 'Telangana' }},
  { pickUpLocation : {city : 'Chennai', state: 'Telangana' }}
);

Это можно сделать довольно легко с помощью lodash.

import _ from 'lodash'

const isSubset = (aSubset, aSuperset) => (
    _.every(aSubset, (val, key) => _.isEqual(val, aSuperset[key]))
)

использование:

const object1 = { pickUpLocation: { city: 'Hyderabad', state: 'Telangana' }}
const object2 = { dist: 322, pickUpLocation:  { city: 'Hyderabad', state: 'Telangana' }}

isSubset(object1, object2)

Использование Lodash isMatch

_.isMatch({prop: 'object', id: 3}, {prop: 'object'})

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


приведенный выше ответ с использованием lodash имеет ограничение и не охватывает все сценарии крайнего случая. Я только что придумал это решение, которое соответствует всем сценариям

import _ from 'lodash';

isSubset(obj1, obj2) {
  let matched = true;
  _.forEach(obj1, (value, key) => {
    if(!requirements || !_.isEqual(value, obj2[key])) {
      matched = false;
      return;
    }
  });
  return matched;
}

Пример 1:

const obj1 = { foo: 'bar' };
const obj2 = { foo: 'bar', baz: 'qux' };
console.log(isSubset(obj1, obj2)); // true

Пример 2:

const obj1 = { foo: 'bar' };
const obj2 = { foo: 'bar' };
console.log(isSubset(obj1, obj2)); // true

Случай 3:

const obj1 = { foo: 'bar', baz: 'qux' };
const obj2 = { foo: 'bar'};
console.log(isSubset(obj1, obj2)); // false

пример 4:

const obj1 = undefiend;
const obj2 = undefiend;
console.log(isSubset(obj1, obj2)); // true

пример 5:

const obj1 = undefiend;
const obj2 = { foo: 'bar'};
console.log(isSubset(obj1, obj2)); // true

пример 6:

const obj1 = { foo: 'bar'};
const obj2 = undefiend;
console.log(isSubset(obj1, obj2)); // false

первый ответ Nima не может быть правильным, так как для условия подмножества должно быть true, все (не просто некоторые) элементы в" меньшем "наборе должны содержаться в" большем " наборе. Остальное в основном правильно, хотя, просто замените some С every и поменять местами два объекта (big и small):

/**
 * Determine whether "small" is a subset of "big"
 * @see https://stackoverflow.com/questions/35737312/find-if-an-object-is-subset-of-another-object-in-javascript/48971177#48971177
 */
function isSubset(big, small) {
  const { every, isEqual } = _;
  return every(small, 
    (v, k) => isEqual(v, big[k])
  );
}

// test it!
var object1 = { pickUpLocation : {city : 'Hyderabad', state: 'Telangana' }};
var object2 = { dist : 322, pickUpLocation:  {city : 'Hyderabad', state: 'Telangana' }};
var a = {i:1, j:2, k:3}; var b = {i:1, j:2}; var c = {i:2, j:2};

console.log([
  isSubset(a, b),
  isSubset(a, c),
  isSubset(b, a),
  isSubset(object1, object2),
  isSubset(object2, object1)
]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>

PS: вот еще один способ сделать это, но, вероятно, медленнее, так как он копирует stuff и не останавливается рано:

function isSubset(big, small) { 
  const { pick, isEqual } = _;
  return isEqual(pick(big, Object.keys(small)), small);
}

вот простое решение:

  import _ from "lodash"
  // is a subset of b?
  function isSubset(a, b, merge = false) {
    const assign = merge ? _.merge : _.assign;
    var c = assign(_.cloneDeep(b), a);
    return _.isEqual(b, c);
  }

function isSubset(obj1, obj2) {
  for (var key in obj2){
     if (JSON.stringify(obj2[key]) === JSON.stringify(obj1[key]))
        return true;
  }
  return false;
}

Edit: Now является общим, но если вы хотите, чтобы он был более общим, вы должны увидеть ссылку для сравнения https://stackoverflow.com/a/1144249/5965782