json对象的完整路径

时间:2016-09-17 13:09:18

标签: javascript algorithm tree

我正在尝试展平一个对象,其中键将成为叶节点的完整路径。我可以递归地识别哪些是叶节点但是试图构建整个路径。

示例输入:

{
  one: 1,
  two: {
    three: 3
  },
  four: {
    five: 5,
    six: {
      seven: 7
    },
    eight: 8
  },
  nine: 9
}

输出:

{
  one: 1,
  'two.three': 3,
  'four.five': 5,
  'four.six.seven': 7,
  'four.eight': 8,
  nine: 9
}

9 个答案:

答案 0 :(得分:10)

您可以使用递归的approch并收集对象的键。该提案也会查找数组。



function getFlatObject(object) {
    function iter(o, p) {
        if (Array.isArray(o) ){
            o.forEach(function (a, i) {
                iter(a, p.concat(i));
            });
            return;
        }
        if (o !== null && typeof o === 'object') {
            Object.keys(o).forEach(function (k) {
                iter(o[k], p.concat(k));
            });
            return;
        }
        path[p.join('.')] = o;
    }

    var path = {};
    iter(object, []);
    return path;
}

var obj = { one: 1, two: { three: 3 }, four: { five: 5, six: { seven: 7 }, eight: 8 }, nine: 9 },
    path = getFlatObject(obj);
	
console.log(path);




答案 1 :(得分:1)

var obj = {
  one: 1,
  two: {
    three: 3
  },
  four: {
    five: 5,
    six: {
      seven: 7
    },
    eight: 8
  },
  nine: 9
};

function flatten(obj) {
  var flatObj = {}

  function makeFlat(obj, path) {
    var keys = Object.keys(obj);
    if (keys.length) {
      keys.forEach(function (key) {
        makeFlat(obj[key], (path ? path + "." : path) + key);
      })
    } else {
      flatObj[path] = obj;
    }
  }
  makeFlat(obj, "");
  return flatObj;
}

console.log(flatten(obj));

答案 2 :(得分:0)

使用最新的JS功能,如对象传播和Object.entries,它应该非常简单:

function flatObj(obj, path = []) {
    let output = {};

    Object.entries(obj).forEach(([ key, value ]) => {
        const nextPath = [ ...path, key ];

        if (typeof value !== 'object') {
            output[nextPath.join('.')] = value;

            return;
        }

        output = {
            ...output,

            ...flatObj(value, nextPath)
        };
    });
}

请注意,此代码可能不是最佳代码,因为每次我们要合并它时都会复制对象。更多地将它视为它的外观,而不是一个完整的最终解决方案。

答案 3 :(得分:0)

部分解决方案: 将输入作为函数的完整路径,它为您提供相应的输出

app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintHorizontal_bias=".5"

答案 4 :(得分:0)

一种非奇特的方法,内部使用递归。



var x = { one:1,two:{three:3},four:{five: 5,six:{seven:7},eight:8},nine:9};
var res = {};
var constructResultCurry = function(src){ return constructResult(res,src); }
        
function constructResult(target, src) {
  if(!src) return;
  target[src.key] = src.val;
}
        
function buildPath(key, obj, overAllKey) {
  overAllKey += (overAllKey ? "." : "") + key;
  if(typeof obj[key] != "object") return { key : overAllKey, val : obj[key] };
  Object.keys(obj[key]).forEach(function(keyInner) {
     constructResultCurry(buildPath(keyInner, obj[key], overAllKey));  
  });
}
        
Object.keys(x).forEach(function(k){
  constructResultCurry(buildPath(k, x, ""));
});

console.log(res);




答案 5 :(得分:0)

您可以按照以下步骤进行操作;

var obj = {one: 1, two: {three: 3}, four: {five: 5, six: {seven: 7}, eight: 8}, nine: 9},
flatObj = (o,p="") => { return Object.keys(o)
                                     .map(k => o[k] === null           ||
                                               typeof o[k] !== "object" ? {[p + (p ? ".":"") + k]:o[k]}
                                                                        : flatObj(o[k],p + (p ? ".":"") + k))
                                     .reduce((p,c) => Object.assign(p,c));
                      };
console.log(flatObj(obj));

答案 6 :(得分:0)

我找到了一个很小的JavaScript实用程序来使用路径访问属性。它称为object-path,是GitHub上的一个开源项目。

要从对象获取属性:

objectPath.get(obj, "a.b");

设置属性:

objectPath.set(obj, "a.b", value);

删除属性:

objectPath.del(obj, "a.b");

太简单了!

答案 7 :(得分:0)

您可以通过使用此功能来实现:

const obj = {
  one: 1,
  two: {
    three: 3
  },
  four: {
    five: 5,
    six: {
      seven: 7
    },
    eight: 8
  },
  nine: 9
}


const flatObject = (obj, keyPrefix = null) =>
  Object.entries(obj).reduce((acc, [key, val]) => {
    const nextKey = keyPrefix ? `${keyPrefix}.${key}` : key

    if (typeof val !== "object") {
      return {
        ...acc,
        [nextKey]: val
      };
    } else {
      return {
        ...acc,
        ...flatObject(val, nextKey)
      };
    }

  }, {});
  
  console.log(flatObject(obj))

答案 8 :(得分:0)

这是一个使用 object-scan 的交互式解决方案。

object-scan 是一个数据处理工具,所以这里的主要优点是在提取所需信息的同时,很容易做进一步的处理或处理

// const objectScan = require('object-scan');

const myData = { one: 1, two: { three: 3 }, four: { five: 5, six: { seven: 7 }, eight: 8 }, nine: 9 };

const flatten = (data) => {
  const entries = objectScan(['**'], {
    reverse: false,
    rtn: 'entry',
    joined: true,
    filterFn: ({ isLeaf }) => isLeaf
  })(data);
  return Object.fromEntries(entries);
};

console.log(flatten(myData));
// => { one: 1, 'two.three': 3, 'four.five': 5, 'four.six.seven': 7, 'four.eight': 8, nine: 9 }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@13.8.0"></script>

免责声明:我是object-scan

的作者