第 92 题:已知数据格式,实现一个函数 fn 找出链条中所有的父级 id

发布于 2022-07-14 16:11:29 字数 428 浏览 273 评论 58

const value = '112'
const fn = (value) => {}
fn(value) // 输出 [1, 11, 112]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(58

热鲨 2022-05-04 13:55:49
function dfsFn(list, value) {
  let res = []

  function dfs(arr, ids=[]) {
    for (const item of arr) {
      if (item.id === value) {
        res = [...ids, ...[item.id]]
        return
      } else {
        if (item.children) {
          dfs(item.children, ids.concat([item.id]))
        }
      }
    }
  }

  dfs(list)

  return res
}

如若梦似彩虹 2022-05-04 13:55:49
const data = [{
    id: '1',
    name: 'test1',
    children: [
        {
            id: '11',
            name: 'test11',
            children: [
                {
                    id: '111',
                    name: 'test111'
                },
                {
                    id: '112',
                    name: 'test112'
                }
            ]
        },
        {
            id: '12',
            name: 'test12',
            children: [
                {
                    id: '121',
                    name: 'test121'
                },
                {
                    id: '122',
                    name: 'test122'
                }
            ]
        }
    ]
}];

let res = [];

const findId = (list, value) => {
  let len = list.length;

  for (let i in list) {
    const item = list[i];

    if (item.id == value) {
      return res.push(item.id), [item.id];
    }

    if (item.children) {
      if (findId(item.children, value).length) {
        res.unshift(item.id);
        return res;
      }
    }

    if (i == len - 1) {
      return res;
    }
  }
};

// res =  []
findId(data, '123'); 

// res = [ '1' ]
findId(data, '1');   

// res = [ '1', '12' ]      
findId(data, '12');    

// res = [ '1', '12', '122' ]  
findId(data, '122');    
我是男神闪亮亮i 2022-05-04 13:55:49
function getIdChain(data, id, idkey = "id", childrenKey = "children") {
  if (check(data, id)) {
    return [];
  }

  loop.chain = [];
  loop(data, id);
  return loop.chain;

  function check(data, id) {
    return !Array.isArray(data) || !data.length || (!id && id !== 0);
  }

  function loop(arr, v) {
    if (check(arr, v)) {
      return false;
    }
    return arr.some(i => {
      return i[idkey] === v || (i[childrenKey] && loop(i[childrenKey], v))
        ? (loop.chain.unshift(i[idkey]), true)
        : false;
    });
  }
}


蝶…霜飞 2022-05-04 13:55:49

评论好多直接复制黏贴都是错的,发之前先测试一下啊,另外如果按照示例中省市区id的规则,可以找到目标 id 然后直接推倒出所有父 id 的吧....

let res = []
let value = '112'
for(let i = 0;i<value.length;i++){
    res.push(value.slice(0,i+1))
}
console.log(res)
自由如风 2022-05-04 13:55:49

const value = '112'
const fn = (value) => {
let vals = value.split('');
//1 11 112
for (let i = 0; i < vals.length; i++) {
let v = vals.slice(0,i+1).join('')
console.log(v)
}
}
fn(value)

百合的盛世恋 2022-05-04 13:55:49
const fn = (str) => [...str].reduce((prev, next) => [...prev, prev.slice(-1) + next], [])
少跟Wǒ拽 2022-05-04 13:55:49
const bfs = data => {
  const queue = [...data]
  let res = []
  while(queue.length) {
    let node = queue.shift()
    if (node.children) {
      for (let child of node.children) {
        queue.push(child)
      }
      res.push(node.id)
    }
  }
  return res
}
吹梦到西洲 2022-05-04 13:55:49

评论好多直接复制黏贴都是错的,发之前先测试一下啊,另外如果按照示例中省市区id的规则,可以找到目标 id 然后直接推倒出所有父 id 的吧....

let res = []
let value = '112'
for(let i = 0;i<value.length;i++){
    res.push(value.slice(0,i+1))
}
console.log(res)

仔细看了下题目意图应该是通过这个id值 解析出所有父级链路,但是根据数据截图,这样推演下去34个省 可能会出现 3411 34512 这就没法玩了 省应该至少占两位 01 - 34 ; 为了出题而出的题 ,没有实用价值

寂寞美少年 2022-05-04 13:55:49
const tree = {
  id: '1',
  name: 'test1',
  children: [
      {
          id: '11',
          name: 'test11',
          children: [
              {
                  id: '111',
                  name: 'test111'
              },
              {
                  id: '112',
                  name: 'test112'
              }
          ]
      },
      {
          id: '12',
          name: 'test12',
          children: [
              {
                  id: '121',
                  name: 'test121'
              },
              {
                  id: '122',
                  name: 'test122'
              }
          ]
      }
  ]
};

interface Area {
  id: string,
  name: string,
  children?: Array<Area>
};

function findAllParentId(tree: Area, id: string) {
  const stack = [tree];
  while(stack.length > 0) {
    const top = stack.slice().pop();
    if (top.id === id) break;

    if (top.children && top.children.length>0) {
      const cTop = top.children.pop();
      stack.push(cTop);
    } else {
      stack.pop();
    }
  }
  return stack.map(n => n.id);
}

const deepCopy = obj => JSON.parse(JSON.stringify(obj));
const idList = findAllParentId(deepCopy(tree), '122');
console.log(`${idList}`);

经典数据结构的深度遍历结构

终陌 2022-05-04 13:55:49

dfs

const fn = (data, value) => {
  let res = []
  const dfs = (arr, temp = []) => {
    for (const node of arr) {
      if (node.children) {
        dfs(node.children, temp.concat(node.id))
      } else {
        if (node.id === value) {
          res = temp
        }
        return
      }
    }
  }
  dfs(data)
  return res
}

为什么运行结果不对

木落 2022-05-04 13:55:49

@wangyuanyuan0521
@ZodiacSyndicate

function fn(data, value) {
  let res = []
  const dfs = (arr, temp = []) => {
    for (const node of arr) {
      if (node.id === value) {
        res = temp
        return
      } else {
        node.children && dfs(node.children, temp.concat(node.id))
      }
    }
  }
  dfs(data)
  return res
}
云归处 2022-05-04 13:55:49
const cityData = [{
    id: '1',
    name: '广东省',
    children: [
      {
        id: '11',
        name: '深圳市',
        children: [
          {
            id: '111',
            name: '南山区'
          },
          {
            id: '112',
            name: '福田区',
            children: [{
              id: '1121',
              name: 'A街道'
            }]
          }
        ]
      },
      {
        id: '12',
        name: '东莞市',
        children: [
          {
            id: '121',
            name: 'A区'
          },
          {
            id: '122',
            name: 'B区',
          }
        ]
      }
    ]
  }];

  const tarId = '1121'
  const findId = (data, tarId, parentId = []) =>
    data.reduce((acc, item) =>
      acc.concat(item.id == tarId
        ? [...parentId, item.id]
        : item.children
          ? findId(item.children, tarId, [...parentId, item.id])
          : [])
      , [])

  let res = findId(cityData, tarId) // 输出 [1, 11, 112, 1121]
  console.log(res)
差↓一点笑了 2022-05-04 13:55:49

源码

const fn = (value, radix = 1) =>
  Array.from(new Array(value.length / radix)).reduce(
    (al, _, idx) => [...al, value.slice(0, radix * (idx + 1))],
    []
  );

测试

fn('112') // ["1", "11", "112"]
fn('123456789', 3) // ["123", "123456", "123456789"]

解释

用途:用来把地址串转换为地址数组,常用于地址选择器,这里支持任何方式分割(常用于6 位地址每两位分割一次)
原理很简单,字符串是有规律的(每个更详细串包含父级串),就是简单的字符串分割(循环每次取前radix*(idx+1)范围的子串)

妖妓 2022-05-04 13:55:49

评论好多直接复制黏贴都是错的,发之前先测试一下啊,另外如果按照示例中省市区id的规则,可以找到目标 id 然后直接推倒出所有父 id 的吧....

let res = []
let value = '112'
for(let i = 0;i<value.length;i++){
    res.push(value.slice(0,i+1))
}
console.log(res)

其实我也想问这个问题:

  • 如果id是有规律的,最容易处理,通过id解析出结果, 其他情况的重点是优先找到目标节点
  • 如果id的位数和层级有关系, 处理方法就要根据id,判断不同的层级, 做不同的处理(少很多递归)
  • 如果id和层级没有关系,就需要权衡是深度优先还是广度优先做处理
青柠芒果 2022-05-04 13:55:49
const arr = [
    {
        id: 1,
        name: '广东',
        children: [
            {
                id: 11,
                name: '深圳',
                children: [
                    {
                        id: 111,
                        name: '南山区'
                    },
                    {
                        id: 112,
                        name: '福田区'
                    }
                ]
            }
        ]
    }
]

const id = 112

const fn = (treeData, idsList = [], ids = []) => {
    treeData.forEach(item => {
        const { id, children } = item
        const tempIds = [].concat(ids)
        tempIds.push(id)

        idsList.push(tempIds);

        if (children && !!children.length) {
            fn(children, idsList, tempIds);
        }
    });

    return idsList;
};

const list = fn(arr)


const result = list.filter(item => {
    const lastValue = item[item.length - 1]

    return Number(lastValue) === Number(id)
})

思路:
1、将数组转换为多个一维数组,结果如下所示:

2、循环第一步所得的结果,判断最后一位是不是和要查询的id相同,如果是那么就返回结果

天气好吗我好吗 2022-05-04 13:55:49

为了可读性,牺牲了部分复杂度。

代码:

function fn(id, list) {
  const match = list.find(item => item.id === id);
  if (match) return [id];
  const sub = list.find(item => id.startsWith(item.id));
  return [sub.id].concat(fn(id, sub.children));
}
千纸鹤 2022-05-04 13:55:49
const data = [{
    id: '1',
    name: 'test1',
    children: [
        {
            id: '11',
            name: 'test11',
            children: [
                {
                    id: '111',
                    name: 'test111'
                },
                {
                    id: '112',
                    name: 'test112'
                }
            ]

        },
        {
            id: '12',
            name: 'test12',
            children: [
                {
                    id: '121',
                    name: 'test121'
                },
                {
                    id: '122',
					name: 'test122',
					children:[
						{
							id: '1221',
							name: 'test121'
						},
					]
                }
            ]
        }
    ]
}];

function findValue(data,valie){
	var key = [];
	function find (data,value){
		for(let i=0; i<data.length;i++){
			if(data[i].id === value){
				key.push(data[i].id)
				break
			}
			if(data[i].children && data[i].children.length > 0){
				if(find(data[i].children,value).length > 0){
					key.push(data[i].id)
					break;
				}
			}
		}
		return key
	}
	find(data,valie)
	return key
}
console.log(findValue(data,'1221'))

刚好有类似需求,试完答案竟然基本都是错的,自己试试。

const data = [{
  id: 1,
  children: [{
    id: 2,
    children: [{
      id: 3
    }, {
      id: 4
    }]
  }]
}];

let find = (function () {
  let map = null;
  let findMap = (data, ids, map = {}) => {
    data.forEach(item => {
      map[item.id] = map[item.id] || [];
      if (ids) {
        map[item.id] = ids.concat(item.id);
      } else {
        map[item.id].push(item.id);
      }
      if (item.children) {
        return findMap(item.children, map[item.id], map);
      }
    });
    return map;
  }
  return function (value) {
    if (!map) {
      map = findMap(data);
    }
    return map[value];
  }
})();

console.log(find(1)) // [1]
console.log(find(2)) // [1, 2]
console.log(find(3)) // [1, 2, 3]
console.log(find(4)) // [1, 2, 4]
抱着落日 2022-05-04 13:55:49
const data = [{
    id: '1',
    name: 'test1',
    children: [
        {
            id: '11',
            name: 'test11',
            children: [
                {
                    id: '111',
                    name: 'test111'
                },
                {
                    id: '112',
                    name: 'test112'
                }
            ]

        },
        {
            id: '12',
            name: 'test12',
            children: [
                {
                    id: '121',
                    name: 'test121'
                },
                {
                    id: '122',
                    name: 'test122'
                }
            ]
        }
    ]
}];

function fn(id, arr) {
    let target = []
    function rfn(finArr, cArr = []) {
        let newArr = [...cArr]
        if (finArr instanceof Array) {
            finArr.find(item => {
                if (item.id === id) {
                    target = [...newArr, item.id]
                    return true
                } else {
                    if (item.children) {
                        rfn(item.children, [...newArr, item.id])
                        if (target.length > 0) {
                            return true
                        }
                    } else {
                        return false
                    }

                }
            })
        }
    }
    rfn(arr)
    return target

}

console.log(fn('112', data));

不知道这样可以不
思路是每次遍历之前都利用结构记录一下层级,如果知道对应的id,直接返回即可

粉红×色少女 2022-05-04 13:55:49
var searched = [];
var stack = [];
var has = false;
var id = '24';
function DFS(arr) {
  //深度遍历
  if (isEnd(arr)) {
    if (arr.id == id) {
      return true;
    } else {
      stack.pop();
    }
  }
  for (var i = 0; i < arr.child.length; i++) {
    var node = arr.child[i];
    if (has) {
      break;
    }
    if (!searched.includes(node.id)) {
      searched.push(node.id);
      stack.push(node.id);
      if (DFS(node)) {
        has = true;
        return stack;
      }
    }
  }
  return stack;
}
function isEnd(arr) {
  if (!arr.child || arr.id == id) {
    return true;
  }
}
深海夜未眠 2022-05-04 13:55:49

`const list = [{
id: '1',
name: '广东省',
children: [{
id: '11',
name: '深圳市',
children: [{
id: '111',
name: '南山区'
},
{
id: '112',
name: '福田区'
}
]
}]
}]

const value = '112'
const fn = (value, list) => {
let queue = [...list], res = [], level = 0
while(queue.length) {
debugger
let length = queue.length
for (let i = 0; i < length; i++) {
let node = queue.shift()
if (node.id === value) {
res.push(node.id)
} else {
if (value.slice(0, level + 1) === node.id) {
res.push(node.id)
}
node.children && queue.push(...node.children)
}
}
level++
}

return res

}
console.log(fn(value, list))`

广度优先遍历

天暗了我发光 2022-05-04 13:55:49

@wangyuanyuan0521
@ZodiacSyndicate

function fn(data, value) {
  let res = []
  const dfs = (arr, temp = []) => {
    for (const node of arr) {
      if (node.id === value) {
        res = temp
        return
      } else {
        node.children && dfs(node.children, temp.concat(node.id))
      }
    }
  }
  dfs(data)
  return res
}

if (node.id === value) {
temp.push(node.id)
res = temp
return
}

澉约 2022-05-04 13:55:49
var value = '112'
let res = []
function fn(data, temp = []) {
  for(node of data) {
    if(node.id === value) {
	res = temp
	break
     }
     if(node.children) {
	fn(node.children, [...temp, ...[node.id]])
     } 
   }
  return [...res, ...[value]]
}
风轻花落早 2022-05-04 13:55:49
// 回溯
function fn(list, value) {
  let res = []
  function helper(list, node) {
    if (node.id === value) {
      res = [...list]
      return
    }
    if (!node.children || !node.children.length) {
      return
    }
    for (let item of node.children) {
      list.push(item.id)
      helper(list, item)
      list.pop()
    }
  }
  helper([], {children:list})
  return res
}
风吹过旳痕迹 2022-05-04 13:55:49
function findFather(list, targetId, path = []) {
        const len = list.length;
        for (let i = 0; i < len; i++) {
          console.log(list[i].id);
          if (list[i].id === targetId) {
            path.push(targetId);
            break;
          } else if (list[i].children) {
            path.push(list[i].id);
            findFather(list[i].children, targetId, path);
          } else if (list[i].id !== targetId && i === len-1) {
            path.pop();
          }
        }
        return path;
      }
时光与爱终年不遇 2022-05-04 13:55:49

const info = [{ id: '1', name: '广东省', children: [{ id: '11', name: '深圳市', children: [{ id: '111', name: '南山区', }, { id: '112', name: '福田区' }] }] }]; const fn = (value) => { let res = null; const dfs = (data, path) => { data.forEach((item) => { if (item.id === value) { path.push(item.id); res = path; return; }; if (item.children) { path.push(item.id); dfs(item.children, path); } }); }; dfs(info, []); return res; };

绝情姑娘 2022-05-04 13:55:49

`var list = [{
id: '1',
children: [{
id: '11',
children: [{
id: '111'
}, {
id: '112'
}]
}, {
id: '12',
children: [{
id: '121'
}, {
id: '122'
}]
}]
}]

let result = [];
function findParentId(list2, val) {
for (let key of list2) {
console.log(key)
if (key.id === val) {
result.push(key.id);
return result;
}
if (key.children) {
result.push(key.id);
let re = findParentId(key.children, val);
if (re && re.length) {
return re;
} else {
result.pop();
}`

笑红尘 2022-05-04 13:55:49
function findId(list) {
    let arr = []
    list.map(item => {
        arr.push(item.id)
        item.children && arr.push(findId(item.children))
    })
    return arr.flat(10)
}
旧伤还要旧人安 2022-05-04 13:55:49

function fnBFS(list, target) {
let resMap = {}

let queue = []
let map = {}
list.forEach(item => {
    queue.push(item)
    map[item.id] = true
})
while(queue.length) {
    let item = queue.shift()
    if(item.children) {
        for(child of item?.children) {
        if(!map[child.id]) {
            queue.push(child)
            map[child.id] = true
            resMap[child.id] = item.id
        }
    }    
    }
}

console.log(resMap)
let res = ''
while(resMap[target]) {
res += ${target} ->
target = resMap[target]
if(!resMap[target]) {
res += target
}
}

console.log(res)
}

软的没边 2022-05-04 13:55:49
const data = [{
            id: '1',
            children: [{
                id: '11',
                children: [{
                    id: '111'
                }, {
                    id: '112'
                }]
            }, {
                id: '12',
                children: [{
                    id: '121'
                }, {
                    id: '122'
                }]
            }]
        },{
            id: '2',
            children: [{
                id: '21',
                children: [{
                    id: '211'
                }, {
                    id: '212'
                }]
            }, {
                id: '22',
                children: [{
                    id: '221'
                }, {
                    id: '222'
                }]
            }]
        }]
        //递归+some(匹配到值结束)
        function findIdList(data,id,parent) {
            const has = data.some(item=>{
                item.value = parent?[...parent.value,item.id]:[item.id]
                if(item.id === id){
                    findIdList.value = item.value
                    return true
                }
                if(item.children){
                    return findIdList(item.children,id,item)
                }
            })
            if(has){
                return findIdList.value
            }
        }
        const result = findIdList(data,"222")
        console.log(result);
淑女气质i 2022-05-04 13:55:49

前缀树 Trie,复杂度仅为需要查找value的长度:

    class Node {
      constructor(isWord = false) {
        this.isWord = isWord;
        this.next = new Map();
      }
    }

    class Trie {
      constructor() {
        this.root = new Node();
      }
      add(key) {
        let cur = this.root;
        for (let i = 0; i < key.length; i++) {
          const c = key[i];
          if (!cur.next.get(c)) {
            cur.next.set(c, new Node());
          }
          cur = cur.next.get(c);
        }
      }
      match(prefix) {
        if (prefix === "") {
          return [];
        }
        let cur = this.root;
        const res = [];
        for (let i = 0; i < prefix.length; i++) {
          const c = prefix[i];
          if (!cur.next.get(c)) {
            return [];
          }
          res.push(prefix.slice(0, i + 1));
          cur = cur.next.get(c);
        }
        return res;
      }
    }

    const trie = new Trie();
    function add(address) {
      for (let i = 0; i < address.length; i++) {
        trie.add(address[i].id);
        if (address[i].children) {
          add(address[i].children);
        }
      }
    }
    add(address);
    trie.match("112"); // [1,11,112]
    trie.match("111"); // [1,11,111]
   trie.match("11"); // [1,11]
   trie.match("110"); // []
绝影如岚 2022-05-04 13:55:49
const data = [{
  id: '1',
  name: 'test1',
  children: [
      {
          id: '11',
          name: 'test11',
          children: [
              {
                  id: '111',
                  name: 'test111'
              },
              {
                  id: '112',
                  name: 'test112'
              }
          ]

      },
      {
          id: '12',
          name: 'test12',
          children: [
              {
                  id: '121',
                  name: 'test121'
              },
              {
                  id: '122',
                  name: 'test122'
              }
          ]
      }
  ]
}];

// 通过递归来实现
function find(arr, value) {
  const result = [];
  for(let i = 0; i < arr.length; i++) {
    const item = arr[i];
    if(item.id === value) {
      return [value]
    }

    if(item.children) {
      const ids = find(item.children, value);
      if(ids.length > 0) {
        result.push(item.id, ...ids);
      }
    }
  }
  return result;
}

console.log(find(data, '11'));
为人所爱 2022-05-04 13:55:49
const data = [
  {
    id: "1",
    name: "test1",
    children: [
      {
        id: "11",
        name: "test11",
        children: [
          {
            id: "111",
            name: "test111"
          },
          {
            id: "112",
            name: "test112"
          }
        ]
      },
      {
        id: "12",
        name: "test12",
        children: [
          {
            id: "121",
            name: "test121"
          },
          {
            id: "122",
            name:
              "test122"
          }
        ]
      }
    ]
  }
]

function find(arr, value) {
  let map = new Map()
  recursion(arr, [], map)
  console.log(map)
  return map.get(value);
}
function recursion(arr, parentArr, map) {
  arr.forEach(item => {
    let _parentArr = parentArr.slice()
    _parentArr.push(item.id)
    map.set(item.id, _parentArr);
    if (item.children && item.children.length > 0) {
      recursion(item.children, _parentArr, map)
    }
  })
}

console.log(find(data, '122'))
家住魔仙堡 2022-05-04 13:55:49

let list = [{
id: '1',
value: '四川省',
children: [{
id: '11',
value: '成都市',
children: [{
id: '111',
value: '高新区'
}, {
id: '112',
value: '天府新区'
}]
}]
}, {
id: '2',
value: '四川省',
children: [{
id: '21',
value: '成都市',
children: [{
id: '211',
value: '高新区'
}, {
id: '212',
value: '天府新区'
}]
}]
}];

function fn(list, id) {
let res = []

function search(list, res) {
let searched = false;
for (let node of list) {
if (node.id === id) {
res.push(node.id)
return true
} else {
if (node.children) {
res.push(node.id)
searched = search(node.children, res);
if (searched) {
return true
}
}
}
}
if (!searched) {
res.pop()
return false
}
}

search(list, res);
return res
}

console.log(fn(list, '212'))

谁的新欢旧爱 2022-05-04 13:55:49

const find04 = (arr, val) => {
let carr = {}
let func = (list, label) => {
list.forEach((item, index) => {
if (carr[label]) {
carr[item.id] = carr[label] + ',' + item.id
} else {
carr[item.id] = item.id
}
if (item.children && item.children.length > 0) {

      func(item.children, item.id)
    }
  })
}
func(arr)
return carr[val].split(',')

}

Spring丶 初心 2022-05-04 13:55:49

@wangyuanyuan0521
@ZodiacSyndicate

function fn(data, value) {
  let res = []
  const dfs = (arr, temp = []) => {
    for (const node of arr) {
      if (node.id === value) {
        res = temp
        return
      } else {
        node.children && dfs(node.children, temp.concat(node.id))
      }
    }
  }
  dfs(data)
  return res
}

这好像没提前返回吧?找到了不需要继续递归了

过去的过去 2022-05-04 13:55:49

// 跟之前总结的树路径查找一个道理

const treePath = (tree, fn) => {
  const path = [], result = [];
  (function forNode(list = [...tree]){
  	list.forEach(node => {
    	path.push(node.id)
       if (fn(node)) result.push(...path)
      node.children && forNode(node.children)
      path.pop()
    })
  })()
  return result
}
console.log(treePath(tree, node => node.id === '212'))
倾城月光淡如水﹏ 2022-05-04 13:55:49

dfs + 回溯

const value = '1221'
const data = [
  {
    id: '1',
    name: '广东省',
    children: [
      {
        id: '11',
        name: '深圳市',
        children: [
          {
            id: '111',
            name: '南山区',
          },
          {
            id: '112',
            name: '福田区',
            children: [
              {
                id: '1121',
                name: 'test',
              },
            ],
          },
        ],
      },
      {
        id: '12',
        name: '广州市',
        children: [
          {
            id: '121',
            name: '天河区',
          },
          {
            id: '122',
            name: '番禺区',
            children: [
              {
                id: '1221',
                name: 'test',
              },
            ],
          },
        ],
      },
    ],
  },
]

function fn(value) {
  function dfs(cur, value, res) {
    if (!cur) {
      return null
    }

    res.push(cur.id)
    if (cur.id === value) {
      return res
    }
    if (cur.children && cur.children.length) {
      for (let node of cur.children) {
        var result = dfs(node, value, res)
        if (result) return result
      }
    }
    res.pop()
  }

  for (let item of data) {
    var result = dfs(item, value, [])
    if (result) {
      return result
    }
  }

  return []
}

console.log(fn(value)) // 输出 [ '1', '12', '122', '1221' ]
舟遥客 2022-05-04 13:55:49
  const data = [{
      id: '1',
      children: [{
          id: '11',
          children: [{
              id: '111',
            },
            {
              id: '112',
            }
          ]

        },
        {
          id: '12',
          children: [{
              id: '121',
            },
            {
              id: '122',
            }
          ]
        }
      ]
    }, {
      id: '2',
      children: [{
          id: '21',
          children: [{
              id: '211',
            },
            {
              id: '212',
            }
          ]

        },
        {
          id: '22',
          children: [{
              id: '221',
            },
            {
              id: '222',
            }
          ]
        }
      ]
    }];

    function traverse(id, data, arr = []) {
      if (data.id === id) {
        arr.push(data)
        arr.done = true
        return arr
      }
      if (data.children) {
        for (const item of data.children) {
          const result = find(id, item, [...arr, data])
          if (result && result.done) {
            return result
          }
        }
      }
    }

    function traverseAll(id, data) {
      for (const item of data) {
        const result = traverse(id, item)
        if (result) {
          return result.reduce((res, cur) => [...res, cur.id], [])
        }
      }
    }

    const result = traverseAll("221", data)
    console.log(result);
独﹏钓一江月 2022-05-04 13:55:49
const solution = (data = [], id) => {
  const stack = [];
  for (let i = 0; i < data.length; i += 1) {
    stack.push(data[i]);
    while (stack.length) {
      const curr = stack.pop();
      if (curr.id === id) return curr.path;

      if (curr.children?.length) {
        const path = curr.path || [curr.id];
        stack.push(
          ...curr.children.map((c) => ({
            ...c,
            path: path.concat(c.id)
          }))
        );
      }
    }
  }
  return [];
};
const data = [
  {
    id: "1",
    name: "test1",
    children: [
      {
        id: "11",
        name: "test11",
        children: [
          {
            id: "111",
            name: "test111"
          },
          {
            id: "112",
            name: "test112"
          }
        ]
      },
      {
        id: "12",
        name: "test12",
        children: [
          {
            id: "121",
            name: "test121"
          },
          {
            id: "122",
            name: "test122"
          }
        ]
      }
    ]
  },
  {
    id: "2",
    name: "test1",
    children: [
      {
        id: "21",
        name: "test11",
        children: [
          {
            id: "211",
            name: "test111"
          },
          {
            id: "212",
            name: "test112"
          }
        ]
      },
      {
        id: "22",
        name: "test22",
        children: [
          {
            id: "221",
            name: "test221"
          },
          {
            id: "222",
            name: "test222"
          }
        ]
      }
    ]
  }
];

console.log(solution(data, "122"));
console.log(solution(data, "222"));
太阳男子 2022-05-04 13:55:49
 let list = [{
            id: '1',
            children: [{
                id: '11',
                children: [{
                    id: '111'
                }, {
                    id: '112'
                }]
            }]
        }];

        function _find(list) {
            let res = [];
            list.forEach(ele => {
                res.push(ele.id);
                if(ele.children && Array.isArray(ele.children)) {
                    res = res.concat(_find(ele.children)) 
                }
            });
            return res;
        }
您的好友蓝忘机已上羡 2022-05-04 13:55:49

dfs

  const find = (id)=>{
    let list = []
    const dfs = function(data){
      for(let i in data){
        let item = data[i]
        if(id === item.id){
          return list.unshift(item.id)
        }
        if(item.children && item.children.length > 0){
          let is = dfs(item.children)
          if(is){
            return list.unshift(item.id)
          }
        }
      }
    }
    dfs(data)
    return list
  }
┼──瘾|| 2022-05-04 13:55:49
export default class FindChildParentIds {
      static data:Array<DataI> = [{
        id: '1',
        name: 'test1',
        children: [
            {
                id: '11',
                name: 'test11',
                children: [
                    {
                        id: '111',
                        name: 'test111'
                    },
                    {
                        id: '112',
                        name: 'test112'
                    }
                ]

            },
            {
                id: '12',
                name: 'test12',
                children: [
                    {
                        id: '121',
                        name: 'test121'
                    },
                    {
                        id: '122',
                        name: 'test122'
                    }
                ]
            },
            {
                id: '13',
                name: 'test13',
                children: [
                    {
                        id: '131',
                        name: 'test121'
                    },
                    {
                        id: '132',
                        name: 'test122'
                    }
                ]
            }
        ]
    }];
    test() {
        console.log('find child parent Ids')
        const parents = FindChildParentIds.dFCPIds('131')
        console.log(parents);
    }
    static dFCPIds(id: string):string{
      // 1 查找父节点
      const p = this.findChildRPid(id,this.data,'')

      // 3 返回结果
      return p
    }
    // 递归算法
    static findChildRPid(id:string,ch: Array<DataI>,pL: string): any {
      let str = ''
      for (const node of ch){
        if(node.id === id){
          return pL +' '+ id;
        } else if (node.children) {
          str = pL + ' ' + node.id
          str = this.findChildRPid( id, node.children, str)
        }
      }
      return str
    }
}

---> 1 13 131

你爱我像她 2022-05-04 13:55:49

回朔法

    const fn = (value) => {
    let result = [];
    const list = [
        {
            id: '1',
            name: '广东省',
            children: [
                {
                    id: '11',
                    name: '深圳市',
                    children: [
                        {
                            id: '111',
                            name: '南山区',
                        },
                        {
                            id: '112',
                            name: '福田区',
                        }
                    ]
                }
            ]
        },
        {
            id: '2',
            name: '福建省',
            children: [
                {
                    id: '21',
                    name: '厦门市',
                    children: [
                        {
                            id: '211',
                            name: '思明区',
                        },
                    ]
                }
            ]
        }
    ];
    for (let i = 0; i < list.length - 1; i++) {
        const trace = [list[i]];
        backtrace(trace, value);
        if (result) {
            return result.map(item => item.id);
        }
    }
    function backtrace(trace, target) {
        const node = trace[trace.length - 1];
        if (node.id === target) {
            result = [...trace];
            return;
        }
        if (!node.children) {
            return;
        }
        for (let i = 0; i < node.children.length; i++) {
            trace.push(node.children[i]);
            backtrace(trace, target);
            trace.pop(); 
        }
}   
 }
console.log(fn('112'));
梦里泪两行 2022-05-04 13:55:49
const data = [{
    id: '1',
    name: 'test1',
    children: [
        {
            id: '11',
            name: 'test11',
            children: [
                {
                    id: '111',
                    name: 'test111'
                },
                {
                    id: '112',
                    name: 'test112'
                }
            ]

        },
        {
            id: '12',
            name: 'test12',
            children: [
                {
                    id: '121',
                    name: 'test121'
                },
                {
                    id: '122',
                    name: 'test122'
                }
            ]
        }
    ]
}];

function flat(tree,value){
    const arr={};
    function flatTree(tree,parent){//先把tree打平借用之前88题思想
        tree.forEach(item=>{
            if(item.children){
                item.parentId = parent||'0'
                arr[item.id]=item;
                flatTree(item.children,item.id);
            }else{
                item.parentId = parent||'0'
                arr[item.id]=item;
            }
        })
        
    }
    flatTree(tree)
    const handle=[];
    function find(value){
        if(arr[value]){
            handle.unshift(value);
            let parentId = arr[value].parentId;
            if(parentId){
                find(parentId); 
            }
        }
        return handle;
    }
    arr[value];
    const result = find(value);
    return result;
}
const flatList = flat(data,'112');
作业与我同在 2022-05-04 13:55:49
const data = [{
    id: 1,
    name: '广东',
    children: [{
        id: 11,
        name: '深圳市',
        children: [{
            id: 111,
            name: '南山区'
        }, {
            id: 112,
            name: '福田区'
        }]
    }]
}, {
    id: 2,
    name: '湖南',
    children: [{
        id: 22,
        name: '郴州市',
        children: [{
            id: 222,
            name: '桂阳'
        }, {
            id: 223,
            name: '燕塘'
        }]
    }]
}]

const getParents = (val, arr = []) => {
    for (let i in arr) {
        // 找到当前目标节点
        if (arr[i].id === val) {
            return [false]
        }
        if (arr[i].children) {
            const parentIdArr = getParents(val, arr[i].children)
            // parentIdArr 不为空,说明找到了目标节点,当前节点为目标节点的子节点
            if (parentIdArr.length) {

                return parentIdArr[0] ?  [arr[i].id, ...parentIdArr ] : [arr[i].id]
            }
        }
    }
    return []
}
console.log(getParents(112, data))
闻呓 2022-05-04 13:55:49

深度优先

  • 直接把路径带过去,遍历到就直接返回
/**
 * dfs
 * @author waldon
 * @date 2022-04-08
 * @param {*} value - param
 * @param {*} arr - param
 */
function getArr(value, arr) {
  function getChildren(_arr, path = []) {
    for (const item of _arr) {
      if (item.id === value) {
        path.push(item.id)
        return path
      } else if (item.children) {
        path.push(item.id)
        return getChildren(item.children, [...path])
      }
    }
  }
  return getChildren(arr)
}
const data = [
  {
    id: '1',
    name: 'test1',
    children: [
      {
        id: '11',
        name: 'test11',
        children: [
          {
            id: '111',
            name: 'test111',
          },
          {
            id: '112',
            name: 'test112',
          },
        ],
      },
      {
        id: '12',
        name: 'test12',
        children: [
          {
            id: '121',
            name: 'test121',
          },
          {
            id: '122',
            name: 'test122',
          },
        ],
      },
    ],
  },
]
console.log(getArr('112', data))
和影子一齐双人舞 2022-05-04 13:55:49

简单的回溯,找到之后停止继续查找

function findParents(id, data) {
  let res;
  const path = [];
  
  backTrack(data);
  return res;
  
  function backTrack(arr) {
    if (res) return;
    
    for (let i = 0; i < arr.length; i++) {
      if (arr[i].id === id) {
        path.push(id);
        res = [...path];
        return;
      }
      
      if (arr[i].children) {
        path.push(arr[i].id);
        backTrack(arr[i].children);
        path.pop();        
      }
    }
  }
}

const data = [{
    id: '1',
    name: 'test1',
    children: [
        {
            id: '11',
            name: 'test11',
            children: [
                {
                    id: '111',
                    name: 'test111'
                },
                {
                    id: '112',
                    name: 'test112'
                }
            ]

        },
        {
            id: '12',
            name: 'test12',
            children: [
                {
                    id: '121',
                    name: 'test121'
                },
                {
                    id: '122',
                    name: 'test122'
                }
            ]
        }
    ]
}];

console.log(findParents('112', data));
疧_╮線 2022-05-04 13:55:45
const data = [{
    id: '1',
    name: 'test1',
    children: [
        {
            id: '11',
            name: 'test11',
            children: [
                {
                    id: '111',
                    name: 'test111'
                },
                {
                    id: '112',
                    name: 'test112'
                }
            ]
        },
        {
            id: '12',
            name: 'test12',
            children: [
                {
                    id: '121',
                    name: 'test121',
                    children: [
                        {
                            id: '1221',
                            name: 'test121',
                            children:[
                                {
                                    id:'12345'
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
},
{
    id:'1234',
    children:[
        {
            id:'567'
        }
    ]
}
]
const value = '112'
const fn = (value) => {
    let err = 'return start'
    let interim = JSON.parse(JSON.stringify(data))
    let result = []
    try {
        while (interim.length > 0) {
            let point = interim.pop() 
            let child = point.children
            let queue = child
            let cresult = []
            result.push(point.id)
            while (queue && queue.length > 0) {
                let cpoint = queue.pop()
                cresult.push(cpoint.id)
                if (!cpoint.children || cpoint.id == value) {
                    if (cresult.indexOf(value) > -1) {
                        queue.length = 0
                    } else {
                        cresult = []
                    }
                    continue
                }
                queue.push(...cpoint.children)
            }
            if (result.concat(cresult).indexOf(value) > -1) {
                result = result.concat(cresult)
                throw new Error(err)
            } else {
                result = []
            }
        }
    } catch (e) {
        if (e.message === err) {
            console.log(result.map(v => parseInt(v)))
            return result.map(v => parseInt(v))
        } else {
            throw e
        }
    }

}
fn(value) // 输出 [1, 11, 112]
fn('1234') // 输出 [1234]
fn('12345') // 输出 [1, 12, 121, 1221, 12345]

写法是深度优先, 增加了数据结构的深度与广度,能可以正确输出

别想她╰ 2022-05-04 13:55:34
/*
* 已知数据格式,实现一个函数 fn 找出链条中所有的父级 id 
* 实现: 通过es6的class实现,思路:递归调用,下传当前的父辈的id
*/
class FindFather{
    constructor() {
        this.data = this.init(),
        this.target = null;
    }
    dfs(value,data,idArr) {
        var that = this;
        data.forEach((item, index) => {
            item.idArr = idArr.concat(item.id)
            if(item.id === value) {
                this.target = item.idArr;
            }
            if(item.children){
                return this.dfs(value, item.children, item.idArr)
            }
        })
    }
    result() {
        return this.target;
    }
    init() {
        return [{
            id: '1',
            name: 'test1',
            children: [
                {
                    id: '11',
                    name: 'test11',
                    children: [
                        {
                            id: '111',
                            name: 'test111'
                        },
                        {
                            id: '112',
                            name: 'test112'
                        }
                    ]

                },
                {
                    id: '12',
                    name: 'test12',
                    children: [
                        {
                            id: '121',
                            name: 'test121'
                        }
                    ]
                }
            ]
        }];
    }
    
}
var find = new FindFather();
find.dfs('112',find.data, [])
console.log(find.result())  //["1","12","121"]
深海夜未眠 2022-05-04 13:55:14
        const fn = (value) => {
            let graph = []
            const mapData = new Map();
            function ParentMap(data, parentId) {
                parentId = parentId || 0;
                data.forEach(item => {
                    mapData[item.id] = { ...item, parentId }
                    if (item.children) {
                        ParentMap(item.children, item.id);
                    }
                })
            }
            ParentMap(data)
            function getId(data, value) {
                graph.unshift(data[value].id)
                if (data[value].parentId !== 0) {
                    getId(data, data[value].parentId)
                }
            }
            getId(mapData, value)
            return graph;
        }
随波逐流 2022-05-04 13:54:06
  • bfs利用队列实现,循环中做的是push => shift => push => shift
  • dfs利用栈实现,循环中做的是push => pop => push => pop

刚刚好,中间仅仅差了一个数组方法:

function bfs(target, id) {
  const quene = [...target]
  do {
    const current = quene.shift()
    if (current.children) {
      quene.push(...current.children.map(x => ({ ...x, path: (current.path || current.id) + '-' + x.id })))
    }
    if (current.id === id) {
      return current
    }
  } while(quene.length)
  return undefined
}

function dfs(target, id) {
  const stask = [...target]
  do {
    const current = stask.pop()
    if (current.children) {
      stask.push(...current.children.map(x => ({ ...x, path: (current.path || current.id) + '-' + x.id })))
    }
    if (current.id === id) {
      return current
    }
  } while(stask.length)
  return undefined
}

// 公共的搜索方法,默认bfs
function commonSearch(target, id, mode) {
  const staskOrQuene = [...target]
  do {
    const current = staskOrQuene[mode === 'dfs' ? 'pop' : 'shift']()
    if (current.children) {
      staskOrQuene.push(...current.children.map(x => ({ ...x, path: (current.path || current.id) + '-' + x.id })))
    }
    if (current.id === id) {
      return current
    }
  } while(staskOrQuene.length)
  return undefined
}
紫﹏色ふ单纯 2022-05-04 13:37:04

@ZodiacSyndicate
这个写法想查112的时候不就查不出来了..

流殇 2022-05-04 12:19:34
const findItem = (value, list, graph) => {
    return list.some(item => {
        if (item.id === value) {
            graph.push(item.id)
            return true
        }
        if (item.children) {
            graph.push(item.id)
            return findItem(value, item.children, graph)
        }
    })
}

const fn = value => {
    let graph = []
    list.some(item => {
        graph.push(item.id)
        if (item.id === value) return true
        if (item.children) {
            let res = findItem(value, item.children, graph)
            if (!res) graph = []
            return res
        }
    })
    return graph
}

实现的思路是记录每次 dfs 遍历的路径,当找到元素时,返回记录的所有路径,找不到时清空路径遍历下个元素
希望有更好的解法

var list = [{
	id: '1',
	children: [{
		id: '11',
		children: [{
			id: '111'
		}, {
			id: '112'
		}]
	}, {
		id: '12',
		children: [{
			id: '121'
		}, {
			id: '122'
		}]
	}]
}]

const value = '122';

这个情景不太对吧

嗯我再研究一下~

〆凄凉。 2022-05-04 11:50:49
const findItem = (value, list, graph) => {
    return list.some(item => {
        if (item.id === value) {
            graph.push(item.id)
            return true
        }
        if (item.children) {
            graph.push(item.id)
            return findItem(value, item.children, graph)
        }
    })
}

const fn = value => {
    let graph = []
    list.some(item => {
        graph.push(item.id)
        if (item.id === value) return true
        if (item.children) {
            let res = findItem(value, item.children, graph)
            if (!res) graph = []
            return res
        }
    })
    return graph
}

实现的思路是记录每次 dfs 遍历的路径,当找到元素时,返回记录的所有路径,找不到时清空路径遍历下个元素

希望有更好的解法

var list = [{
	id: '1',
	children: [{
		id: '11',
		children: [{
			id: '111'
		}, {
			id: '112'
		}]
	}, {
		id: '12',
		children: [{
			id: '121'
		}, {
			id: '122'
		}]
	}]
}]

const value = '122';

这个情景不太对吧

无声静候 2022-05-04 09:58:22
let list = [{
    id: '1',
    children: [{
        id: '11',
        children: [{
            id: '111'
        }, {
            id: '112'
        }]
    }]
}];

function fn(value) {
    // 回溯的标记
    let _p = Symbol('parent');
    // 找到子节点
    let result;
    function _fn(arr, p) {
        for (let i = 0; i < arr.length; i++) {
            arr[i][_p] = p;
            if (arr[i].id === value) {
                result = arr[i];
                return;
            }
            !result && arr[i].children && _fn(arr[i].children, arr[i])
        }
        if (result) return;
    }
    _fn(list, null);
    let tmp = [];
    if (!result) return null;
    while (result) {
        tmp.unshift(result.id);
        result = result[_p];
    }
    return tmp;
}

思路是找到子节点,再回溯找父节点
复杂度是O(n),循环n次子节点,但是需要额外空间记录父节点引用

夕色琉璃_ 2022-05-03 19:38:06

dfs

const fn = (data, value) => {
  let res = []
  const dfs = (arr, temp = []) => {
    for (const node of arr) {
      if (node.children) {
        dfs(node.children, temp.concat(node.id))
      } else {
        if (node.id === value) {
          res = temp
        }
        return
      }
    }
  }
  dfs(data)
  return res
}
梦中楼上月下 2022-05-02 07:16:40
const data = [{
    id: '1',
    name: 'test1',
    children: [
        {
            id: '11',
            name: 'test11',
            children: [
                {
                    id: '111',
                    name: 'test111'
                },
                {
                    id: '112',
                    name: 'test112'
                }
            ]

        },
        {
            id: '12',
            name: 'test12',
            children: [
                {
                    id: '121',
                    name: 'test121'
                },
                {
                    id: '122',
                    name: 'test122'
                }
            ]
        }
    ]
}];
const find = (value) => {
    let result = [];
    let findArr = data;
    let skey = '';
    for (let i = 0, l = value.length; i < l; i++) {
        skey += value[i]
        let item = findArr.find((item) => {
            return item.id == skey
        });

        if (!item) {
            return [];
        }

        result.push(item.id);
        if (item.children) {
            findArr = item.children;
        } else {
            if (i < l - 1) return []
            return result;
        }

    }

}
//调用看结果
function testFun() {
    console.log('1,11,111:', find('111'))
    console.log('1,11,112:', find('112'))
    console.log('1,12,121:', find('121'))
    console.log('1,12,122:', find('122'))
    console.log('[]:', find('113'))
    console.log('[]:', find('1114'))
}
~没有更多了~

关于作者

深海夜未眠

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

玍銹的英雄夢

文章 0 评论 0

我不会写诗

文章 0 评论 0

十六岁半

文章 0 评论 0

浸婚纱

文章 0 评论 0

qq_kJ6XkX

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文