OBJECTIVE
Make a function that looks through a list (collection) and returns an array of all objects that have equivalent property values (source).
EXAMPLE #1
function where(collection, source) {
var arr = [];
return arr;
}
where([
{ first: 'Romeo', last: 'Montague' },
{ first: 'Mercutio', last: null },
{ first: 'Tybalt', last: 'Capulet' }],
{ last: 'Capulet' });
EXPECTED OUTPUT #1
[{ first: 'Tybalt', last: 'Capulet' }]
EXAMPLE #2
where(
[{ 'a': 1 },
{ 'a': 1 },
{ 'a': 1, 'b': 2 }],
{ 'a': 1 }),
EXPECTED OUTPUT #2
[{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }]
QUESTIONS
Since you can't use external libraries, here's a simple way to do what you need:
function where(collection, source) {
var keys = Object.keys(source);
return collection.filter(function (item) {
return keys.every(function (key) {
return source[key] == item[key];
});
});
}
-> Solution 1: Using Lodash Where
For this kind of problems, you can use Lodash utility library.
Lodash already has where function which you need.
see the below example.
var out = _.where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' }); document.getElementById('out').innerHTML = JSON.stringify(out); var out2 = _.where( [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], { 'a': 1 }); document.getElementById('out2').innerHTML = JSON.stringify(out2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.8.0/lodash.js"></script> <div id="out"></div> <hr/> <div id="out2"></div>
-> Solution 2: Custom Where
Implementation
This implementation works with strings, single object , one level object and multilevel objects .
function typeOf(o) {
return Object.prototype.toString.call(o).split(' ')[1].split(']')[0].toLowerCase();
}
function isUndefined(o) {
return typeOf(o) === 'undefined';
}
function where(collection, source) {
var checkArr = [];
if (typeOf(collection) === 'object') {
checkArr = [collection];
} else if (typeOf(collection) === 'array') {
checkArr = collection;
}
function isObjectSemiSame(obj, source, u) {
return Object.keys(source).every(function(key) {
if (isUndefined(obj) || isUndefined(obj[key])) {
return;
}
if (typeOf(source[key]) === 'object' || typeOf(source[key]) === 'array') {
return isObjectSemiSame(obj[key], source[key]);
}
return source[key] === obj[key];
});
}
return checkArr.filter(function(item) {
return isObjectSemiSame(item, source);
});
}
Jasmine tests for testing where
with strings, single object, one level object and multilevel objects.
function typeOf(o) { return Object.prototype.toString.call(o).split(' ')[1].split(']')[0].toLowerCase(); } function isUndefined(o) { return typeOf(o) === 'undefined'; } function where(collection, source) { var checkArr = []; if (typeOf(collection) === 'object') { checkArr = [collection]; } else if (typeOf(collection) === 'array') { checkArr = collection; } function isObjectSemiSame(obj, source, u) { return Object.keys(source).every(function(key) { if (isUndefined(obj) || isUndefined(obj[key])) { return; } if (typeOf(source[key]) === 'object' || typeOf(source[key]) === 'array') { return isObjectSemiSame(obj[key], source[key]); } return source[key] === obj[key]; }); } return checkArr.filter(function(item) { return isObjectSemiSame(item, source); }); } describe('where method', function() { it('testing with strings', function() { var collection = [ "one", "two", "three" ]; var collection = [ "bamboo", "two", "bamboo", "link" ]; expect(where(collection, "two")).toEqual(["two"]); expect(where(collection, "bamboo")).toEqual(["bamboo", "bamboo"]); }); it('testing with one object', function() { var collection1 = { name: 'raju', age: 23, }; var collection2 = { name: 'Friko', age: 36, }; expect(where(collection1, { name: 'raju' })).toEqual([collection1]); expect(where(collection1, { name: 'Dump' })).toEqual([]); expect(where(collection2, { age: 36 })).toEqual([collection2]); expect(where(collection2, { car: 'audi' })).toEqual([]); }); it('testing with one level object', function() { var collection = [{ name: 'jack', age: 25 }, { name: 'missi', age: 23 }, { name: 'reddy', age: 46 }]; var source1 = { name: 'reddy' }; var source2 = { age: 25 }; expect(where(collection, source1)).toEqual([collection[2]]); expect(where(collection, source2)).toEqual([collection[0]]); }); it('testing with multilevel object', function() { var collection = [{ name: 'jack', age: 25, level1: { name: 'l1', level2: { name: 'l2', level3: { name: 'l3' } } } }, { name: 'missi', age: 23, level1: { name: 'l1' } }, { name: 'reddy', age: 46, feature: { flag: false } }]; var source1 = { level1: { name: 'l1' } }; var source2 = { level1: { name: 'l1', level2: { name: 'l2' } } }; var source3 = { feature: { flag: false } }; expect(where(collection, source1).length).toBe(2); expect(where(collection, source1)).toEqual(jasmine.arrayContaining([ collection[0], collection[1] ])); expect(where(collection, source2)).toEqual([collection[0]]); expect(where(collection, source3)).toEqual([collection[2]]); }); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine.min.js"></script> <link href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine.min.css" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine-html.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/boot.min.js"></script>
UPDATE: added custom where
implementation with jasmine tests
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.