6

There is data returned from server containing an array of strings as hierarchy like this:

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

how do i create a tree data structure out of it to make Output the data in tree form.

like this:

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

what is the most simple way to do so ?

and is there any way to reverse it ? for example of asked knife i want to return house.kitchen.knife

thanks in advance

2
  • 2
    please add the wanted structure as javascript array/object? and what you have tried. Commented Aug 2, 2018 at 20:45
  • @NinaScholz i have not tried anything yet because i couldn't find any answer for something like this using strings, i tried to separate the ( . ) but i failed. Commented Aug 2, 2018 at 20:47

4 Answers 4

5

You could take an array with nested arrays where the first element is the name.

For finding a wanted string, it uses a recursive approach by keeping the path to the actual elements for later joining a wanted string.

... right, why an array and not a funky object? Glad that you asked. Arrays allows to maintain a specific order without relying on actual implementation of ordered objects.

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; }

Sign up to request clarification or add additional context in comments.

1 Comment

worked perfectly is is there any way to reverse it ? for example of asked knife i want to return house.kitchen.knife
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));

This code will return this structure in mainMap in both ways:

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": {}
            }
        }
    }
}

2 Comments

worked perfectly is is there any way to reverse it ? for example of asked knife i want to return house.kitchen.knife
Sure, for this you should use a reverse map as well. Edited the answer.
3

here's one way to do it, might not be the most efficient, but works. If you don't want the leafs as empty objects, you can modify it as needed.

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

1 Comment

worked perfectly is is there any way to reverse it ? for example of asked knife i want to return house.kitchen.knife
-2

Code below will give you the last string that includes the keyword. Let me know if this wasn't what you were looking for.

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.