字符串数组转换为树形数据结构

6

服务器返回的数据中包含一个字符串数组,其层次结构如下:

[
 "house.bedroom.bed",
 "house.kitchen.spoon",
 "house.kitchen.knife",
 "house.bedroom.sofa",
 "house.bedroom.tv",
 "plants.trees",
 "house.birds.parrot.grey"
 ...]

如何创建一棵树形数据结构以使输出的数据呈现树状形式。

如下所示:

root
  house
    bedroom
      bed
      sofa
      tv
    kitchen
      spoon
      knife
    birds
      parrot
        grey
  plants
    trees

最简单的方法是什么?

是否有反向的方法?例如,如果输入knife,我想返回house.kitchen.knife

提前感谢。


2
请提供您尝试过的内容,并将所需结构添加为JavaScript数组/对象。 - Nina Scholz
@NinaScholz 我还没有尝试过任何东西,因为我找不到使用字符串解决这样问题的答案,我尝试分离 ( . ) 但失败了。 - John Dawn
4个回答

5
你可以使用嵌套数组,其中第一个元素是名称。
为了找到所需的字符串,它使用递归方法,通过保留实际元素的路径以便稍后连接所需的字符串。
... 是的,为什么要使用数组而不是花哨的对象呢?很高兴你问。数组可以维护特定顺序,而不依赖于有序对象的实际实现。

function find([key, values], string, temp = []) {
    var result;
    temp = temp.concat(key);
    if (key === string) {
        return temp.slice(1).join('.');
    }
    values.some(a => result = find(a, string, temp));
    return result;
}

var array = ["house.bedroom.bed", "house.kitchen.spoon", "house.kitchen.knife", "house.bedroom.sofa", "house.bedroom.tv", "plants.trees", "house.birds.parrot.grey"],
    result = array.reduce((r, s) => {
        ('root.' + s).split('.').reduce((a, item) => {
            var array = a.find(([v]) => v === item);
            if (!array) {
                a.push(array = [item, []]);
            }
            return array[1];
        }, r);
        return r;
    }, []).pop();

console.log(find(result, 'knife')); // house.kitchen.knife
console.log(find(result, '42'));    // undefined, what else?
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }


工作得很完美,有没有办法反转它?例如,如果我要求刀子,我想返回house.kitchen.knife。 - John Dawn

4

const data = [
    "house.bedroom.bed",
    "house.kitchen.spoon",
    "house.kitchen.knife",
    "house.bedroom.sofa",
    "house.bedroom.tv",
    "plants.trees",
    "house.birds.parrot.grey"
];

const mainMapFromStart = {};
const mainMapFromEnd = {};
function set(parts, mainMap) {
    let map = mainMap;
    for(const item of parts) {
        map[item] = map[item] || {};
        map = map[item];
    }
}

data.map(item => item.split('.')).forEach(parts => {
    set(parts, mainMapFromStart);
    set(parts.reverse(), mainMapFromEnd);
});

console.log(JSON.stringify(mainMapFromStart, null, 4));
console.log(JSON.stringify(mainMapFromEnd, null, 4));

这段代码将以两种方式在mainMap中返回此结构:
output:
{
    "house": {
        "bedroom": {
            "bed": {},
            "sofa": {},
            "tv": {}
        },
        "kitchen": {
            "spoon": {},
            "knife": {}
        },
        "birds": {
            "parrot": {
                "grey": {}
            }
        }
    },
    "plants": {
        "trees": {}
    }
}
{
    "bed": {
        "bedroom": {
            "house": {}
        }
    },
    "spoon": {
        "kitchen": {
            "house": {}
        }
    },
    "knife": {
        "kitchen": {
            "house": {}
        }
    },
    "sofa": {
        "bedroom": {
            "house": {}
        }
    },
    "tv": {
        "bedroom": {
            "house": {}
        }
    },
    "trees": {
        "plants": {}
    },
    "grey": {
        "parrot": {
            "birds": {
                "house": {}
            }
        }
    }
}

1
工作得很完美,有没有办法将其反转?例如,如果我要求刀子,我想返回house.kitchen.knife。 - John Dawn
当然,为此你也应该使用一个反向映射。已编辑答案。 - Shl

3

以下是一种方法,可能不是最高效的,但可以实现。如果您不想将叶子节点作为空对象,请根据需要进行修改。

var r=[
 "house.bedroom.bed",
 "house.kitchen.spoon",
 "house.kitchen.knife",
 "house.bedroom.sofa",
 "house.bedroom.tv",
 "plants.trees",
 "house.birds.parrot.grey"];

var o={}; // output object
function build(o,p){
 p.split(".").forEach(function(d){
   o = o[d] || (o[d]={});  
 });
}    

r.forEach(function(a,i){ // build up each branch based on path
 build(o, a);
});
o

工作得很完美,有没有办法反转它?例如,如果我要求刀子,我想返回house.kitchen.knife。 - John Dawn

-2
下面的代码将为您提供包含关键字的最后一个字符串。如果这不是您要找的,请告诉我。

let stringsArray = [
  "house.bedroom.bed",
  "house.kitchen.spoon",
  "house.kitchen.knife",
  "house.bedroom.sofa",
  "house.bedroom.tv",
  "plants.trees",
  "house.birds.parrot.grey"
];

function findInArray() {
let keyword = document.getElementById('search').value;
  let results = document.getElementById('results');
  stringsArray.forEach(function(string, index) {
    if (string.includes(keyword)) {
      results.innerHTML = string;
    }
  });
}
<label for="search">Search for:</label>
<input type="text" id="search">
<button type="button" onclick='findInArray()'>Search</button>

<span id="results"></span>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接