8

次のようなネストされたオブジェクトがあるとします。

var cars = {
    "bentley": {
        "suppliers": [
            {
            "location": "England",
            "name": "Sheffield Mines"}
        ]
        // ...
    }
};

このような配列["bentley", "suppliers", "0", "name"]、つまり、最も深い要素を抽出する既存の関数はありますか。つまりpluck_innards(cars, ['bentley', "suppliers", "0", "name"])、「Sheffield Mines」を返します。

言い換えれば、関数 (名前を付けますdeep_pluck) はありますか?

deep_pluck(cars, ['bentley', 'suppliers', '0', 'name']) 
         === cars['bentley']['suppliers']['0']['name']

これは単純ですが、jQuerylo-dash /underscore などの Javascript ユーティリティ ライブラリの 1 つでおそらく行われているほど一般的であるように思えますが、私はそれを見たことがありません。

私の考えは、次のような些細なことです。

function deep_pluck(array, identities) {
    var this_id = identities.shift();
    if (identities.length > 0) {
        return deep_pluck(array[this_id], identities);
    }
    return array[this_id];
}

私はjsFiddleに投稿しました。

もちろん、配列内の数値インデックスがいつ必要になるかを識別するのに十分なほど関数がスマートであれば、それは役に立ちます。他にどのような注意事項が懸念されるかはわかりません。

これはすべて、すでに巧妙に解決されていると私が想像するものに対するかなり長い質問ですが、そこにどのような解決策があるのか​​ に興味があるので、これを投稿することにしました.

4

4 に答える 4

2

配列インデックスを数値として渡せば、問題は発生しないと思います0

再帰のない関数の代替バージョンは次のとおりです。

function deep_pluck(object, identities) {
    var result = object;
    for(var i = 0; i < identities.length; i++) {
        result = result[identities[i]];
    }
    return result;
}

ここでの実例:http://jsfiddle.net/AmH2w/1/

于 2012-10-08T16:20:46.300 に答える
1

汎用ライブラリではありませんが、CasperJSはそのようなutils.getPropertyPath機能を備えているようです。

/**
 * Retrieves the value of an Object foreign property using a dot-separated
 * path string.
 *
 * Beware, this function doesn't handle object key names containing a dot.
 *
 * @param  Object  obj   The source object
 * @param  String  path  Dot separated path, eg. "x.y.z"
 */
function getPropertyPath(obj, path) {
    if (!isObject(obj) || !isString(path)) {
        return undefined;
    }
    var value = obj;
    path.split('.').forEach(function(property) {
        if (typeof value === "object" && property in value) {
            value = value[property];
        } else {
            value = undefined;
        }
    });
    return value;
}

編集:

それ以来、これを解決するための実装に出くわしました。

  1. Ben Alman による getObject プラグイン ( Github)
  2. 私が転がしたもの -要旨を参照

編集 (2014)

また、比較的新しいlodash.deep.

于 2012-10-12T02:23:46.617 に答える
1

dotty.get(obj, pathspec) はそれを行い、配列またはドット付き文字列をパススペックとして受け入れます。

Dottyはオープン ソースであり、exists メソッドとパターもあります。

方法論は再帰であり、あなたのアイデアに非常に似ていますが、存在しないものの要素にアクセスしようとして例外をスローしないように、dotty には null/undefined オブジェクトのテストが含まれている点が異なります。

ドキュメントのdotty.get() ソースは以下に掲載されています。

var get = module.exports.get = function get(object, path) {
  if (typeof path === "string") {
    path = path.split(".");
  }

  if (!(path instanceof Array) || path.length === 0) {
    return;
  }

  path = path.slice();

  var key = path.shift();

  if (typeof object !== "object" || object === null) {
    return;
  }

  if (path.length === 0) {
    return object[key];
  }

  if (path.length) {
    return get(object[key], path);
  }
};
于 2013-07-19T15:21:08.763 に答える
0

を使用した短い ES6 実装を次に示しreduceます。

function get(obj, keyPath) {
    return keyPath
        .split(".")
        .reduce((prev, curr) => prev[curr], obj);
}

使用法:

get(cars, "bentley.suppliers.0.name") // -> "Sheffield Mines"
于 2016-09-14T12:21:42.380 に答える