【问题标题】:Deep picking using Underscore.JS使用 Underscore.JS 进行深度拾取
【发布时间】:2016-09-28 17:32:35
【问题描述】:

我正在尝试使用 underscoreJs 来操作 JavaScript 对象并遇到问题。

这是我的例子

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]

我在上面尝试过,但总是不确定。感谢您对此提供的任何帮助。

【问题讨论】:

  • 您是否有机会将您的 JSON 包装到一个数组中?由于 Underscore 使用集合(其中确实包含一个包含所有类型对象的数组),将您的 JSON 写入一个数组将解决您的问题。 codepen.io/anon/pen/WGroRm?editors=0011
  • @torazburo 感谢您的建议。我肯定知道 parse 和 JSON 的含义。我可能错误地使用了 parse 这个词,但我将其称为 JSON 文档的意图是正确的,因为我一直在处理 JSON 文档。我通过跳过将 JSON 文档解析为 Javascript 对象的部分给出了一个示例。另外,恕我直言,您使用的操纵词不正确,提取会很好。我尊重他人:)

标签: javascript underscore.js lodash


【解决方案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 只是一种方便的方法,它将 data 的 parent 属性传递给 findCallIndexInParent(这将检索 call 所在的索引)并返回所需的对象 数组。

Lodash(下划线的一个分支)提供了一种获取对象属性的方法,该方法在这里非常方便(遗憾的是,下划线没有它)。

findCallIndexInParent的解释如下:

  1. 链接父列表
  2. 提取资源数组
  3. 作为 pluck 映射,它返回一个列表列表,因此需要展平。
  4. 查找 calls 包含 call 的元素的索引
  5. 返回 parent 中包含 call 的对象的值(索引)。

这是fiddle。希望对您有所帮助。

【讨论】:

  • 感谢您的明确解释。感谢您的时间和帮助。
【解决方案2】:

这似乎可以解决问题。

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>

【讨论】:

  • 感谢您的帮助。
【解决方案3】:

如果我理解正确,您想获取 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

【讨论】:

    猜你喜欢
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-11
    • 2017-01-07
    • 2018-03-28
    • 1970-01-01
    相关资源
    最近更新 更多