如果值与包含嵌套对象值的任何值匹配,则返回true

时间:2017-03-08 03:58:49

标签: javascript object lodash

我有一个嵌套对象,包括:

var obj = {
  id: 1,
  name: 'Stephen',
  age: 18,
  department: {
    id: 1,
    text: 'Operations'
  }
}

因此,如果我有一个字符串或一组值匹配任何值,包括集合中的嵌套对象值,它将返回true。我尝试使用lodash的_.includes,但我不知道如何遍历嵌套对象。

_.includes(obj.department, 'Operations')

我想做的更像是

_.includes(obj, ['Stephen', 'Operations']) //返回true

5 个答案:

答案 0 :(得分:1)

使用递归Array#some检查值是否存在。当谓词的结果为Array#some时,true会立即返回。

var obj = {
  id: 1,
  name: 'Stephen',
  age: 18,
  department: {
    id: 1,
    text: 'Operations'
  }
}

function recursiveIncludes(obj) {
  var values = [].slice.call(arguments, 1);
  
  return Object.keys(obj).some(function(key) {
    var current = obj[key];
 
    if(values.indexOf(current) !== -1) {
      return true;
    }
    
    if(typeof current === 'object' && current !== null) {
      return recursiveIncludes.apply(null, [current].concat(values));
    }
    
    return false;
  });
}

console.log('Operations: ', recursiveIncludes(obj, 'Operations'));
console.log('Moses, Stephen: ', recursiveIncludes(obj, 'Moses', 'Stephen'));
console.log('Moses, 58: ', recursiveIncludes(obj, 'Moses', 58));

答案 1 :(得分:0)

这是一种递归方法。它将对象的所有属性(叶属性)提取到数组中。然后,您可以在其上调用_.includes()。

var obj = {
  id: 1,
  name: 'Stephen',
  age: 18,
  department: {
    id: 1,
    text: 'Operations'
  }
}

function objToArray(obj) {
    var result = [];
    for (const prop in obj) {
        const value = obj[prop];
        if (typeof value === 'object') {
            result = result.concat(toArray(value)); 
        }
        else {
            result.push(value);
        }
    }
    return result;
}

_.includes(objToArray(obj), ['Stephen', 'Operations'])

答案 2 :(得分:0)

给定一个字符串数组,这将检查该属性是否以递归方式存在。



var obj = {
  id: 1,
  name: 'Stephen',
  age: 18,
  department: {
    id: 1,
    text: 'Operations'
  }
}

function hasValues(obj, props)
{
  var keys = Object.keys(obj);
  for(var i = 0; i < keys.length; i++){
    var item = obj[keys[i]];
    // If the item is a string or number, do a comparison
    if(typeof item === "string" || typeof item === "number"){
      var idx = props.indexOf(item);
      if(idx >= 0) props.splice(idx, 1);
    // If it's an object then search the object recursively
    } else if(typeof item === "object"){
      hasValues(item, props);
    }
  }

  return props.length === 0;
}

console.log(hasValues(obj, ['Stephen', 'Operations']))
console.log(hasValues(obj, [18, 1]))
console.log(hasValues(obj, [18, '13lkj4']))
&#13;
&#13;
&#13;

答案 3 :(得分:0)

您可以使用flatMap作为一种机制,在flatMap回调函数中使用map以递归方式展平所有值。获取所有值后,我们使用difference来获取objectvalues之间所有值之间的差异。最后,我们使用isEmpty检查结果差异是否为空。

function includesDeep(object, values) {
  return _(obj)
  .flatMap(function cb(v) { return _.isObject(v)? _.map(v, cb): v; })
  .thru(_.partial(_.difference, values))
  .isEmpty();
}

var result = includesDeep(obj, ['Stephen', 'Operations']);

&#13;
&#13;
var obj = {
  id: 1,
  name: 'Stephen',
  age: 18,
  department: {
    id: 1,
    text: 'Operations'
  }
};

function includesDeep(object, values) {
  return _(obj)
  .flatMap(function cb(v) { return _.isObject(v)? _.map(v, cb): v; })
  .thru(_.partial(_.difference, values))
  .isEmpty();
}

var result = includesDeep(obj, ['Stephen', 'Operations']);

console.log(result);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
&#13;
&#13;
&#13;

答案 4 :(得分:-2)

测试显示您无法检查多值和&amp;与lodash相关的深度值包括,所以你必须为自己编写一个函数。

您的解决方案

describe('includes', () => {
    var value = {
        foo: 'bar',
        fuzz: 'buzz',
        value2: {
            key: 'value'
        }
    };

    function includes(collection, values) {
        return [].concat(values).every((value) => {
            return Object.keys(collection).some((key) => {
                let it = collection[key];
                return typeof it == 'object' ? includes(it, value) : _.includes(it, value);
            })
        });
    }

    it('check single value', () => {
        expect(includes(value, 'bar')).toBe(true);
        expect(includes(value, 'baz')).toBe(false);
    });

    it('check multi values', () => {
        expect(includes(value, ['bar', 'buzz'])).toBe(true);
        expect(includes(value, ['baz', 'buzz'])).toBe(false);
    });

    it('check value in depth', () => {
        expect(includes(value, 'value')).toBe(true);
        expect(includes(value, 'no-exists')).toBe(false);
    });
});

测试

describe('includes', () => {
    var value = {
        foo: 'bar',
        fuzz: 'buzz',
        value2: {
            key: 'value'
        }
    };

    it('check single value', () => {
        expect(_.includes(value, 'bar')).toBe(true);
        expect(_.includes(value, 'baz')).toBe(false);
    });

    it('check multi values', () => {
        expect(_.includes(value, ['bar', 'buzz'])).toBe(false);
        expect(_.includes(value, ['baz', 'buzz'])).toBe(false);
    });

    it('check value in depth', () => {
        expect(_.includes(value, 'value')).toBe(false);
    });
});

function includes(collection, values) {
    return [].concat(values).every(function (value) {
        return Object.keys(collection).some(function (key) {
            var it = collection[key];
            return (typeof it == 'object') ? includes(it, value) : _.includes(it, value);
        });
    });
}


var obj = {
  id: 1,
  name: 'Stephen',
  age: 18,
  department: {
    id: 1,
    text: 'Operations'
  }
};


var tests=[
  "Operations",
  "Non-Existing Value",
  ['Stephen', 'Operations'],
  ['Stephen', 'Non-Existing Value'],
];


tests.forEach(function(test){
  console.log("includes(obj,"+JSON.stringify(test)+") => "+ includes(obj,test));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>