Создать путь из свойства объекта javascript

Допустим, у меня есть следующий объект JavaScript

var obj = {
            a:{
                b:"value",
                c:{
                    d:"value2"
                }
            }
        }

Какая функция будет при вводе с объектом "d" (например, function getPath(obj, d)), вывести строку "acd"? Я пробовал разные вещи, включая путь к объектам, но, похоже, он не предназначен для этого.

4 ответа

Вы можете использовать итеративный и рекурсивный подход.

function getPath(object, key) {

    function iter(o, p) {
        if (typeof o === 'object') {
            return Object.keys(o).some(function (k) {
                return iter(o[k], p.concat(k));
            });
        }
        if (p[p.length - 1] === key) {
            path = p;
            return true;
        }
    }

    var path = [];
    iter(object, []);
    return path.join('.');
}

console.log(getPath({ d: { d: { d: { d: 'val' } } } }, 'd'));
console.log(getPath({ a: { b: 'value', c: { d: 'value2' } } }, 'd'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

У меня было довольно много веселья при составлении этого, он генерирует список всех возможных путей, которые можно сделать из объекта, и возвращает самый длинный путь, заканчивающийся правильным ключом, он возвращает пустую строку not found:

function getPath(obj, key) {
    paths = []

    function getPaths(obj, path) {
        if (obj instanceof Object && !(obj instanceof Array)) {
            for (var k in obj){
                paths.push(path + "." + k)
                getPaths(obj[k], path + "." + k)
            }
        }
    }

    getPaths(obj, "")
    return paths.map(function(p) {
        return p.slice(p.lastIndexOf(".") + 1) == key ? p.slice(1) : ''
    }).sort(function(a, b) {return b.split(".").length - a.split(".").length;})[0];
}

var obj = { a:{ b:"value", c:{ d:"value2"}}};
console.log(getPath(obj, "b"))
console.log(getPath(obj, "c"))
console.log(getPath(obj, "d"))

var obj = { d:{ d:"value", d:{ d:"value2"}}};
console.log(getPath(obj, "d"))

Ну вот. Функция, которую вы хотите использовать findLongestPath:

var obj = {
    a:{
        b:"value",
        c:{
            d:"value2"
        }
    }
};

function findAllPaths(obj, property, startString = '') {
  var pathStrings = [];
  Object.keys(obj).forEach(key => {
    if(typeof obj[key] === 'object') {
      pathStrings.push(...findAllPaths(obj[key], property, startString + key + '.'));
      return;
    }
    
    pathStrings.push(startString + key);
  });
  
  return pathStrings;
}

function findLongestPath(obj, property) {
  return findAllPaths(obj, property)
    .filter(str => str.split('').reverse().join('').slice(0, property.length) === property.split('').reverse().join(''))
    .reduce((longest, next) => longest.length >= next.length ? longest : next, '');
}

console.log(findLongestPath(obj, 'd'));

findAllPaths является рекурсивной функцией, которая перебирает объект и генерирует массив всех возможных путей к объектам. findLongestPath фильтрует эти строки, чтобы убедиться, что последнее свойство соответствует заданному свойству, а затем возвращает самое длинное из них.

Вы можете перебрать объект с помощью рекурсивной функции и сохранить путь следующим образом:

function getPath(object, keyValue, path) {
  for (var k in object) {
    if (k === keyValue) {
      return path + '.' + k;
    }
    else if (typeof object[k] === 'object') {
      return getPath(object[k], keyValue, path !== '' ? path + '.' + k : k);
    }
  }
}

var obj = {
    a:{
        b:"value",
        c:{
            d:"value2"
        }
    }
};

var path = getPath(obj, 'd', '');
console.log(path);

Другие вопросы по тегам