Запрос объекта JavaScript - PullRequest
       2

Запрос объекта JavaScript

0 голосов
/ 10 апреля 2019

Учитывая следующие три объекта, как эффективен способ вернуть первый объект, который содержит пару ключ-значение?

var obj = {
  item1: {
    name: 'apple',
    color: 'red'
  },
  item2: {
    name: 'blueberry',
    color: 'blue'
  },
  item3: {
    name: 'cherry',
    color: 'red'
  }
};

var obj2 = {
  collection: [
    {
      item1: {
        name: 'apple',
        color: 'red'
      },
      item2: {
        name: 'blueberry',
        color: 'blue'
      },
      item3: {
        name: 'cherry',
        color: 'red'
      }
    }
  ]
};

var obj3 = {
  items: [
    {
      item1: {
        name: 'apple',
        color: 'red'
      }
    },
    {
      item2: {
        name: 'blueberry',
        color: 'blue'
      },
    },
    {
      item3: {
        name: 'cherry',
        color: 'red'
      }
    }
  ]
};

Я хотел бы получить те же результаты для следующих трех операторов:

getObject(obj, 'color', 'red');
getObject(obj2, 'color', 'red');
getObject(obj3, 'color', 'red');

Вывод:

{
  name: 'apple',
  color: 'red'
}

Вот что у меня есть, но я думаю, что где-то отсутствует замыкание, поскольку оно разрывается при вызове самой функции:

function getObject(arg, key, val) {
  if (typeof arg!=='object') return null;
  switch (Object.prototype.toString.call(arg)) {
    case '[object Array]':
      for (var i=0; i<arg.length; ++i) {
        getObject(arg[i], key, val);
      }
      break;
    case '[object Object]':
      for (var i in arg) {
        if (arg.hasOwnProperty(i)) {
          if (typeof arg[i]==='object') {
            getObject(arg[i], key, val);
          } else {
            if (i===key && arg[i]===val) {
              return arg;
            }
          }
        }
      }
      break;
  }
}

Ответы [ 4 ]

4 голосов
/ 10 апреля 2019

Вы можете использовать эту функцию, которая также будет искать в более глубоко вложенных структурах данных.

function getObject(obj, prop, value) {
    if (Object(obj) !== obj) return; // It is not an object
    if (obj[prop] === value) return obj; // Found it
    for (var key in obj) {
        var result = getObject(obj[key], prop, value);
        if (result) return result; // Found it
    }
}

var obj = {item1: {name: 'apple',color: 'red'},item2: {name: 'blueberry',color: 'blue'},item3: {name: 'cherry',color: 'red'}};
var obj2 = {collection: [{item1: {name: 'apple',color: 'red'},item2: {name: 'blueberry',color: 'blue'},item3: {name: 'cherry',color: 'red'}}]};
var obj3 = {items: [{item1: {name: 'apple',color: 'red'}},{item2: {name: 'blueberry',color: 'blue'},},{item3: {name: 'cherry',color: 'red'}}]};

console.log(getObject(obj, 'color', 'red'));
console.log(getObject(obj2, 'color', 'red'));
console.log(getObject(obj3, 'color', 'red'));
2 голосов
/ 10 апреля 2019

Вы можете использовать Array#some для быстрого сокращения, если объект найден.

function getObject(object, key, value) {
    var result;
    if (!object || typeof object !== 'object') return;
    if (object[key] === value) return object;
    Object.values(object).some(v => result = getObject(v, key, value));
    return result;
}

var obj = { item1: { name: 'apple', color: 'red' }, item2: { name: 'blueberry', color: 'blue' }, item3: { name: 'cherry', color: 'red' } },
    obj2 = { collection: [{ item1: { name: 'apple', color: 'red' }, item2: { name: 'blueberry', color: 'blue' }, item3: { name: 'cherry', color: 'red' } }] },
    obj3 = { items: [{ item1: { name: 'apple', color: 'red' } }, { item2: { name: 'blueberry', color: 'blue' } }, { item3: { name: 'cherry', color: 'red' } }] };

console.log(getObject(obj, 'color', 'red'));
console.log(getObject(obj2, 'color', 'red'));
console.log(getObject(obj3, 'color', 'red'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 10 апреля 2019

Вы можете вызвать функцию рекурсивно, чтобы добраться до объекта, у которого нет объектов-членов, и отфильтровать его по ключу и значению:

function getObject(obj, k, v) {
    for (var key in obj) {
        if (typeof obj[key] === 'object') {
            return getObject(obj[key], k, v);
        } else if (key === k && obj[key] === v) {
            return(obj);
        }
    }   
}

var obj = {
  item1: {
    name: 'apple',
    color: 'red'
  },
  item2: {
    name: 'blueberry',
    color: 'blue'
  },
  item3: {
    name: 'cherry',
    color: 'red'
  }
};

var obj2 = {
  collection: [
    {
      item1: {
        name: 'apple',
        color: 'red'
      },
      item2: {
        name: 'blueberry',
        color: 'blue'
      },
      item3: {
        name: 'cherry',
        color: 'red'
      }
    }
  ]
};

var obj3 = {
  items: [
    {
      item1: {
        name: 'apple',
        color: 'red'
      }
    },
    {
      item2: {
        name: 'blueberry',
        color: 'blue'
      },
    },
    {
      item3: {
        name: 'cherry',
        color: 'red'
      }
    }
  ]
};
console.log(getObject(obj, 'color', 'red'));
console.log(getObject(obj2, 'color', 'red'));
console.log(getObject(obj3, 'color', 'red'));
0 голосов
/ 10 апреля 2019

Ваш подход в getObject в порядке, однако, как правило, вы должны преобразовать массив для каждого из всех.Вы можете использовать функцию map для подготовки массива к процессу поиска.

Функция find "находит" объект в соответствии с определенным предикатом.

Это при условии, что индексы связаны с ключами -> index i==0 -> items1 и т. Д.

var obj = {item1: {name: 'apple',color: 'red'},item2: {name: 'blueberry',color: 'blue'},item3: {name: 'cherry',color: 'red'}};
var obj2 = {collection: [{item1: {name: 'apple',color: 'red'},item2: {name: 'blueberry',color: 'blue'},item3: {name: 'cherry',color: 'red'}}]};
var obj3 = {items: [{item1: {name: 'apple',color: 'red'}},{item2: {name: 'blueberry',color: 'blue'},},{item3: {name: 'cherry',color: 'red'}}]};

let getObject = (o, key, value) => o.find(obj => obj[key] === value);

console.log(getObject(Object.values(obj), 'color', 'red'));
console.log(getObject(obj2.collection.map((o, i) => o[`item${i+1}`]), 'color', 'red'));
console.log(getObject(obj3.items.map((o, i) => o[`item${i+1}`]), 'color', 'red'));
.as-console-wrapper { min-height: 100%; }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...