2016-09-28 1 views
1

Я пытаюсь использовать underscoreJs для манипулирования объектом JavaScript и проблемы с этим.Глубокий выбор с использованием Underscore.JS

Вот мой пример

var data = { 
 
    "label": "SomeName", 
 
    "parent": [{ 
 
    "id": "parentId", 
 
    "resources": [{ 
 
     "name": "ID1NAME", 
 
     "calls": [ 
 
     "user_get", "user2_post", "user3_delete" 
 
     ] 
 
    }, { 
 
     "name": "ID2", 
 
     "calls": [ 
 
     "employee1_get", "employee2_delete", "employee3_update" 
 
     ] 
 
    }] 
 
    }] 
 
}; 
 
var res = _(data).chain(). 
 
    pluck('parent'). 
 
    flatten(). 
 
    findWhere(function(item){ 
 
    item === "user_get" 
 
    }). 
 
    value(); 
 
    
 
console.log(res);

Используя элемент, который является частью data.parent.calls[] (например: "user_get") Я хотел бы, чтобы извлечь его родительский объект, то есть data.parent[0].

Я пробовал выше, но всегда получаю неопределенный. Я ценю любую помощь по этому поводу.

+0

У вас есть шанс обернуть ваш JSON в массив? Поскольку Underscore использует коллекции (которые содержат массив, поддерживающий все типы объектов), запись вашего JSON в массив решит вашу проблему. https://codepen.io/anon/pen/WGroRm?editors=0011 – Aer0

+0

@torazburo Спасибо за ваше предложение. Я точно знаю значение parse и JSON. Возможно, я неправильно использовал слово parse, но мое намерение назвать его документом JSON верным, поскольку я работал над документом JSON. Я привел пример, пропуская часть, в которой JSON-документ разбирается в объект Javascript. Кроме того, с должным уважением, использование слова, которое вы использовали, неверно, извлечение было бы приятным. Я уважаю других :) –

ответ

1

Одна из проблем, вы испытываете ваше использование _.pluck. Если вы выполните _.pluck над объектом, он перейдет по клавишам объекта, пытаясь получить свойство, указанное вами в качестве второго аргумента (в этом случае «parent»). 'label' - это строка и 'parent' - массив, таким образом, массив, который вы получаете в результате, - [undefined, undefined]. Остальное пойдет не так.

Одним из решений может быть следующим:

function findCallIndexInParent(call, parent) { 
    return _.chain(parent) 
      .pluck('resources') 
      .flatten() 
      .findIndex(function (obj) { 
       return _.contains(obj.calls, call); 
      }) 
      .value(); 
} 

function findCall(call, data) { 
    var parent = data.parent; 
    return parent[findCallIndexInParent(call, parent)]; 
} 

console.log(findCall('user_get', data)); 

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

Lodash (fork of underscore) предоставляет метод получения свойства объекта, который был бы очень полезен здесь (к сожалению, подчеркивание не имеет его).

Объяснение findCallIndexInParent выглядит следующим образом:

  1. Сети родительского список
  2. срывать массив ресурсов
  3. Как карты срывать, он возвращает список списков, так как нужно было сглаживаться.
  4. Найти индекс элемента, который называет содержит вызова
  5. возвращает значение (индекс) объекта, который содержит вызова внутри родителя.

Вот fiddle. Надеюсь, поможет.

+0

Спасибо за четкое объяснение. Цените свое время и помощь. –

1

Казалось бы, этот трюк.

function findByCall(data, call) { 
 
    return _.find(data.parent, function(parent) {   //From data.parent list, find an item that 
 
    return _.some(parent.resources, function(resource) {//has such parent.resource that it 
 
     return _.includes(resource.calls, call);   //includes the searched resource.calls item 
 
    }); 
 
    }); 
 
} 
 

 
//Test 
 

 
var data = { 
 
    "label": "SomeName", 
 
    "parent": [{ 
 
    "id": "parentId", 
 
    "resources": [{ 
 
     "name": "ID1NAME", 
 
     "calls": [ 
 
     "user_get", "user2_post", "user3_delete" 
 
     ] 
 
    }, { 
 
     "name": "ID2", 
 
     "calls": [ 
 
     "employee1_get", "employee2_delete", "employee3_update" 
 
     ] 
 
    }] 
 
    }] 
 
}; 
 

 
console.log(findByCall(data, 'user_get'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>

+0

Я ценю вашу помощь. –

1

Если я правильно понял, вы хотите получить индекс элемента в массиве parent, который имеет любой ресурс с указанным вызовом.

data = { 
 
    "label": "SomeName", 
 
    "parent": [{ 
 
    "id": "parentId", 
 
    "resources": [{ 
 
     "name": "ID1NAME", 
 
     "calls": [ 
 
     "user_get", "user2_post", "user3_delete" 
 
     ] 
 
    }, { 
 
     "name": "ID2", 
 
     "calls": [ 
 
     "employee1_get", "employee2_delete", "employee3_update" 
 
     ] 
 
    }] 
 
    }] 
 
} 
 

 
// find the index of a parent 
 
const index = _.findIndex(data.parent, parent => 
 
    // that has any (some) resources 
 
    _.some(parent.resources, resource => 
 
     // that contains 'user_get' call in its calls list 
 
     _.contains(resource.calls, 'user_get') 
 
    ) 
 
) 
 

 
console.log(index) // 0
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

Если вы хотите, чтобы найти фактический родительский объект, используйте find вместо findIndex

Если вы хотите, чтобы найти все родительские объекты, соответствующие этому вызов, используйте filter вместо findIndex