当前位置: 首页 > 知识库问答 >
问题:

查找对象或数组中字符串的路径

张高义
2023-03-14

给定一个对象或数组,我希望能够确定路径是否存在。

给定 - 示例 1

const spath = "data/message";
const body = {
  data: {
    school: 'yaba',
    age: 'tolu',
    message: 'true'
  },
  time: 'UTC',
  class: 'Finals'
}

它应该返回true,因为可以在body.data.message中找到消息返回false。

给定示例2

const spath = "data/message/details/lastGreeting";
const body = {
  data: {
    school: 'yaba',
    age: 'tolu',
    message: {
       content: 'now',
       details: {
          lastGreeting: true
       }
    }
  },
  time: 'UTC',
  class: 'Finals'
}

它应该返回true,因为lastGreting可以在body.data.message.details.lastGreeting中找到,否则返回false。

另一个条件是当主体由数组组成时

给定示例3

const spath = "data/area/NY";
const body = {
  data: {
    school: 'yaba',
    age: 'tolu',
    names : ['darious'],
    area: [{
       NY: true,
       BG: true
    ]]
    message: {
       content: 'now',
       details: {
          lastGreeting: true
       }
    }
  },
  time: 'UTC',
  class: 'Finals'
}

它应该返回true,因为可以在body.data.area[0]中找到NY。否则返回false。

这是我想出的解决办法

const findPathInObject = (data, path, n) => {
  console.log('entered')
  console.log(data, path)
  

  if(!data){
    return false
  }
  
  let spath = path.split('/');
  for(let i = 0; i<n; i++){
    
    let lastIndex = spath.length - 1;
    if(spath[i] in data && spath[i] === spath[lastIndex]){
      return true
    }
    
    const currentIndex = spath[i];
//     spath.splice(currentIndex, 1);
    return findPathInObject(data[spath[currentIndex]], spath[i+1], spath.length)
    
  }
  
  return false
}

console.log(findPathInObject(body, spath, 3))

共有3个答案

宋宇
2023-03-14

严格来说,body.data.area[0]。NY不在body的路径中,对不起。body.data.area在路径中。对于没有body.data.area作为数组的对象,这里有一个解决方案。如果您想将数组中的对象作为对象路径的一部分包含在内,解决方案会更复杂

const spath = "data/area/NY";
const spath2 = "data/message/details/lastGreeting";
const notPath = "data/message/details/firstGreeting";
const body = {
  data: {
    school: 'yaba',
    age: 'tolu',
    names : ['darious'],
    area: {
       NY: true,
       BG: true
    },
    message: {
       content: 'now',
       details: {
          lastGreeting: true
       }
    }
  },
  time: 'UTC',
  class: 'Finals'
};

console.log(`${spath} exists? ${ exists(body, spath) && `yep` || `nope`}`);
console.log(`${spath2} exists? ${ exists(body, spath2) && `yep` || `nope`}`);
console.log(`${notPath} exists? ${ exists(body, notPath) && `yep` || `nope`}`);

function exists(obj, path) {
  const pathIterable = path.split("/");
  while (pathIterable.length) {
    const current = pathIterable.shift();
    // no path left and exists: true
    if (pathIterable.length < 1 && current in obj) { return true; }
    // up to now exists, path continues: recurse
    if (current in obj) { return exists(obj[current], pathIterable.join("/")); }
  }
  // no solution found: false
  return false;
}
蒋硕
2023-03-14

发现

对于这个答案,我将提供一个< code >树,其中包含不同程度的对象和数组嵌套

const tree =
  { data:
      { school: "yaba", age: "tolu", message: "foo" }
  , classes:
      [ { name: "math" }, { name: "science" } ]
  , deep:
      [ { example:
            [ { nested: "hello" }
            , { nested: "world" }
            ]
        }
      ]
  }

生成器非常适合这类问题。从一个通用的查找开始,它会为特定路径产生所有可能的结果-

function find (data, path)
{ function* loop (t, [k, ...more])
  { if (t == null) return
    if (k == null) yield t
    else switch (t?.constructor)
    { case Object:
        yield *loop(t[k], more)
      break
      case Array:
        for (const v of t)
          yield *loop(v, [k, ...more])
        break
    }
  }
  return loop(data, path.split("/"))
}
Array.from(find(tree, "classes/name"))
Array.from(find(tree, "deep/example/nested"))
Array.from(find(tree, "x/y/z"))
[ "math", "science" ]
[ "hello", "world" ]
[]

find1

如果您想要一个返回一个(第一个)结果的函数,我们可以轻松编写find1。这特别有效,因为生成器是可暂停/可取消的。找到第一个结果后,生成器将停止搜索其他结果-

function find1 (data, path)
{ for (const result of find(data, path))
    return result
}
find1(tree, "data/school")
find1(tree, "classes")
find1(tree, "classes/name")
find1(tree, "deep/example/nested")
find1(tree, "x/y/z")
"yaba"
[ { name: "math" }, { name: "science" } ]
"math"
"hello"
undefined

存在

如果你关心检查一个特定的路径是否存在,我们可以把存在写成 find1 的简单特化 -

const exists = (data, path) =>
  find1(data, path) !== undefined
exists(tree, "data/school")
exists(tree, "classes")
exists(tree, "deep/example/nested")
exists(tree, "x/y/z")
true
true
true
false

演示

展开下面的代码段,以在您自己的浏览器中验证结果 -

function find (data, path)
{ function* loop (t, [k, ...more])
  { if (t == null) return
    if (k == null) yield t
    else switch (t?.constructor)
    { case Object:
        yield *loop(t[k], more)
      break
      case Array:
        for (const v of t)
          yield *loop(v, [k, ...more])
        break
    }
  }
  return loop(data, path.split("/"))
}

function find1 (data, path)
{ for (const result of find(data, path))
    return result
}

const tree =
  { data:
      { school: "yaba", age: "tolu", message: "foo" }
  , classes:
      [ { name: "math" }, { name: "science" } ]
  , deep:
      [ { example:
            [ { nested: "hello" }
            , { nested: "world" }
            ]
        }
      ]
  }

console.log("find1")
console.log(find1(tree, "data/school"))
console.log(find1(tree, "classes"))
console.log(find1(tree, "classes/name"))
console.log(find1(tree, "deep/example/nested"))
console.log(find1(tree, "x/y/z"))
console.log("find")
console.log(Array.from(find(tree, "classes/name")))
console.log(Array.from(find(tree, "deep/example/nested")))
console.log(Array.from(find(tree, "x/y/z")))
危飞文
2023-03-14

您可以事先进行一些检查,检查path是否为临时字符串,然后使用true退出。

通过拥有一个数组,您可以通过省略索引来使用实际路径检查数组的元素,从而提前退出。

对于键的最终检查,您可以检查它是否存在,并使用 rest 路径返回递归调用的结果,或者如果键不在对象中,则返回 false

const
    findPathInObject = (data, path) => {
        if (!path) return true;
        if (!data || typeof data !== 'object') return false;
        if (Array.isArray(data)) return data.some(d => findPathInObject(d, path));

        const
            spath = path.split('/'),
            key = spath.shift();

        return key in data
            ? findPathInObject(data[key], spath.join('/'))
            : false;
    };

console.log(findPathInObject({ data: { school: 'yaba', age: 'tolu', message: 'true' }, time: 'UTC', class: 'Finals' }, "data/message", 3)); // true

console.log(findPathInObject({ data: { school: 'yaba', age: 'tolu', message: { content: 'now', details: { lastGreeting: true } } }, time: 'UTC', class: 'Finals' }, "data/message/details/lastGreeting", 3)); // true

console.log(findPathInObject({ data: { school: 'yaba', age: 'tolu', names: ['darious'], area: [{ NY: true, BG: true }], message: { content: 'now', details: { lastGreeting: true } } }, time: 'UTC', class: 'Finals' }, "data/area/NY", 3)); // true
 类似资料:
  • 我正在阅读一些面试准备材料,我想知道如果字符串或数组中的字符可以是unicode字符,那么解决这个问题的最佳方法是什么。如果它们是严格的ascii,则可以创建一个大小为256的数组,并将每个ascii字符映射到一个索引,该数组中的位置将表示出现的次数。如果字符串有unicode字符,是否仍然可以这样做,即unicode字符的大小是否合理,您可以使用整数数组的索引来表示它?由于unicode字符的大

  • 问题是,我试图这么做,但我检查字符串长度的方法不起作用;我能做些什么来修复它?

  • 问题内容: 在字符串数组中找到最长的字符串有一种简便的方法吗? 像什么? 问题答案: var longest = arr.sort(function (a, b) { return b.length - a.length; })[0]; 可能更有效,但仅自Javascript 1.8 / ECMAScript5起可用,并且在较旧的浏览器中默认不可用:

  • 获取数组,对象或字符串的大小。 Get type of val (array, object or string). Use length property for arrays. Use length or size value if available or number of keys for objects. Use size of a Blob object created from v

  • 问题内容: 我有一个字符串数组,其中包含字符串列表。我想弄清楚此列表中是否有重复的条目。基本上,我有一个用户列表,应该没有重复的条目。 问题答案: 您可以将String数组添加到HashSet 这将为您提供唯一的String值。如有必要,将HashSet转换回数组

  • 我有一个字符串,可以是两种形式之一: 或 其中<代码> {...}和< code>[...]是任何有效的JSON。我只对解析出字符串的JSON部分感兴趣,但是我不确定最好的方法是什么(特别是因为我不知道字符串将是两种形式中的哪一种)。这是我目前的方法: 这是有效的,但我忍不住觉得可以做得更好。我想可能是regex,但我在匹配子对象和数组时遇到了问题,而不是最外部的json对象或数组。有什么建议吗?