Successor in a JavaScript array with multiple dimensions

I am grappling with a complex nested multidimensional array that resembles the following structure in JSON format:

[
    {
        "Object": "Car",
        "Child": [
            {
                "Object": "Toyota",
                "Child": [
                    {
                        "Object": "Prius"
                    },
                    {
                        "Object": "Yaris"
                    }
                ]
            },
            {
                "Object": "Honda",
                "Child": [
                    {
                        "Object": "Accord"
                    },
                    {
                        "Object": "Civic",
                        "Child": [
                            {
                                "Object": "Sedan"
                            },
                            {
                                "Object": "Coupe"
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

I'm seeking a way to determine if one object is a direct descendant of another within this hierarchy.

For instance, "Sedan" is a direct descendant of "Civic", "Honda", and "Car"; however, it is not a direct descendant of "Coupe", "Accord", "Toyota", "Prius", or "Yaris".

The goal is to develop a function similar to the following:

function Lineal_Descendant(A,B){
    /*perform logic here*/
}

Lineal_Descendant("Sedan","Civic") /*should return true*/
Lineal_Descendant("Sedan","Toyota") /*should return false*/
Lineal_Descendant("Prius","Honda") /*should return false*/
Lineal_Descendant("Yaris","Car") /*should return true*/

Answer №1

Alright, I'll take a crack at it: http://jsfiddle.net/nrabinowitz/UJrhK/

function Lineal_Descendant(child, parent) {
    // examining an array of objects
    function walk(array, search) {
        for (var x=0, found; x<array.length; x++) {
            found = visit(array[x], search);
            if (found) return found;
        }
        return false;
    }
    // searching an object and its children
    function visit(obj, search) {
        // identifying the search item
        return obj.Object === search ? obj :
            // not found, but has children
            obj.Child ? walk(obj.Child, search) :
            // no children
            false; 
    }
    // locating the parent
    parent = walk(data, parent);
    // finding child, converting to boolean
    if (parent) return !!walk(parent.Child || [], child);
}

There might be a more elegant solution to this problem, but this should suffice. Keep in mind that your data structure does not enforce unique names, so if you have two items at the same level with identical values for Object, the search results may be unexpected.

Answer №2

This technique may seem unconventional, but it involves utilizing the browser DOM model to achieve certain tasks. By preloading your data structure into the DOM and then using functions like querySelectorAll or similar (such as jQuery), you can manipulate the data effectively.

For a practical example, check out this jsFiddle demonstration - http://jsfiddle.net/SxCD6/2/

Answer №3

Presented below is a compact and recursive function that fulfills the desired requirements:

function linearDescendant(list, search, ancestor, _parent) {
  var i, item, found = false;

  for (i=0; i<list.length; i++) {
    item = list[i];
    item._parent = _parent;

    if (item.Object == search) {
      while (item._parent && item.Object != ancestor) {
        item = item._parent;
      }
      found = item.Object == ancestor;
    } else if (item.Child) { 
      found = linearDescendant(item.Child, search, ancestor, item);
    }
    if (found) break;
  }
  return found;
}

To utilize this function, use the following syntax:

linearDescendant(yourArray, "Sedan", "Civic")  // true
linearDescendant(yourArray, "Sedan", "Toyota") // false
linearDescendant(yourArray, "Prius", "Honda")  // false
linearDescendant(yourArray, "Yaris", "Car")    // true

It should be noted that the function assigns a _parent property to each nested object. This attribute is crucial for conducting the ancestor verification once the target object has been identified.

Answer №4

I implemented the approach of Modified Preorder Tree Traversal to solve this problem. Essentially, I iterated through the JSON object using a recursive function and assigned "left" and "right" values to each element. After updating the entire JSON object with these values, I compared the "left" and "right" values in Object A and B to determine if one is a lineal descendant of the other.

For instance, if Object A is a lineal descendant of Object B, then the "left" value in A will be greater than the "left" value in B, and the "right" value in A will be smaller than the "right" value in B.

Sample Code:

var data = [{"Object":"Car","Child":[{"Object":"Toyota","Child":[{"Object":"Prius"},{"Object":"Yaris"}]},{"Object":"Honda","Child":[{"Object":"Accord"},{"Object":"Civic","Child":[{"Object":"Sedan"},{"Object":"Coupe"}]}]}]}];

alert(Lineal_Descendant(data,'Sedan','Civic'));  //true
alert(Lineal_Descendant(data,'Sedan','Toyota')); //false
alert(Lineal_Descendant(data,'Prius','Honda'));  //false
alert(Lineal_Descendant(data,'Yaris','Car'));    //true

function Lineal_Descendant(data, A, B){
    var i=1,                  
        k=0,                  
        aIndex,               
        bIndex,               
        entry = new Array(),  
        mpttObj = mptt(data); 

    function mptt(obj) {
        for (var f=0, n=obj.length; f<n; f++) {
            if(obj[f].Object==A) aIndex=k; 
            if(obj[f].Object==B) bIndex=k; 

            obj[f].index=k;
            entry[obj[f].index] = {left:i, right:-1};
            obj[f].left=i;
            
            k++;
            i++;

            if (obj[f].Child) mptt(obj[f].Child);

            entry[obj[f].index].right = i;
            obj[f].right=i;
            i++;
        }
        return obj;
    }

    if(entry[aIndex].left>entry[bIndex].left  &&  entry[aIndex].right<entry[bIndex].right) return true;
    else return false;
}

See it in action: http://jsfiddle.net/bPu2V/

Answer №5

Before anything else,

Absolutely do not utilize "Object" as a key on an Object.

You are dangerously close to accidentally overwriting the native javascript Object which would result in the dreaded javascript apocalypse. I recommend using name instead.

Furthermore, this issue can be resolved with a fairly straightforward recursive function:

var find = function(obj, search){
    // return this object if it matches
    if(obj.name === search)
      return obj;
    // false if it has no children
    if(!obj.hasOwnProperty('Child')) 
      return false;
    for(var i=0,u=obj.Child.length;i<u;i++){
        // recursively check each child
        var foundRecursively = find(obj.Child[i], search);
        if(foundRecursively) // match found! return up the chain
            return foundRecursively; 
    }
    // no match, return up the chain
    return false;
};

var Lineal_Descendant = function(A,B){
    // find the B (the parent) in data, then find A in B.  
    // Convert any object into a boolean and return.
    return !!find(find(data[0],B),A);
};

Lineal_Descendant("Sedan","Civic") // true
Lineal_Descendant("Sedan","Toyota") // false
Lineal_Descendant("Prius","Honda") // false
Lineal_Descendant("Yaris","Car") // true

This solution assumes that the data is an array with 1 root Object (as shown by OP in the sample data). Nonetheless, it can be easily modified to handle an array of roots at the outset.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Server-side issue: Ajax POST request returns an empty POST array

I've encountered an issue with my JavaScript function that is supposed to collect data and send it to a PHP file. My problem lies in attempting to submit an array as part of the post: Here's the snippet of the function in question: var string ...

In JavaScript, the function will return a different object if the string in an array matches the

My task involves working with a simple array of string ids and objects. Upon initial load, I am matching these Ids with the objects and setting the checked property to true. const Ids = ['743156', '743157'] [ { "id&quo ...

What is the best way to use the $push operation to add an object to an array within a mongoDB database using Node.js

I am trying to find a way to push an object into an array inside my MongoDB database. When using the $push method with submits[postDate], I am encountering an error with the syntax highlighting the first "[". Any suggestions on how to resolve this issue? ...

Error: The variable "weather" is not defined while using React with the weatherbit API

I'm currently developing a React application that utilizes the Weatherbit API. However, I have encountered an issue with the weather object when calling my data array. Below is the code snippet where the problem occurs: import React from "react&q ...

Issues with the proper functionality of the .ajax() method in Django

I'm currently facing an issue with my Ajax code while trying to interact with the database in order to edit model instances. I noticed that the first alert statement is functioning correctly, however, the subsequent alert statements are not working as ...

Updating information within AngularJS select boxes

On my page, I have 3 select boxes. When a user selects an option in the first select box, I want the options in the second select box to update based on the value selected in the first one. Similarly, I want the options in the third select box to change w ...

Transforming a string representation of a nested array into an actual nested array with the help of JavaScript

My database stores a nested array as a string, which is then returned as a string when fetched. I am facing the challenge of converting this string back into a nested array. Despite attempting to use JSON.parse for this purpose, I encountered the following ...

Page redirects automatically after AJAX call

I'm a beginner when it comes to using AJAX and I am trying to delete a student from a list through an AJAX request. I want the response of the request to be displayed on the same page within a specific div, but instead, the response keeps redirecting ...

What is the best way to format table values as currency?

Still getting the hang of Javascript, and I'm in the process of learning... Currently, my challenge involves calculating the total sum of values within a Bootstrap 4 table and formatting the result as currency (specifically in USD format). While I&ap ...

Retrieving values with Jquery on a function's onClick event

Here is a small script that retrieves values from a select element <script> jQuery(document).ready(function() { var selectedValue = jQuery("#tr_val").val(); }); </script> When you click on this div and execute the open_win function, I need t ...

Receiving serialized post data in array on RESTful Server using CodeIgniter

Can someone guide me on how to retrieve data from a serialized array in CodeIgniter RESTful Server? Ajax $.ajax({ type: 'POST', url: "/mywebsite/api/index.php/purchase", data: $("#formdatatrans").serialize(), success: function(r ...

Include a new class in the classList of an element at a specific index

Is it possible to add a class to a specific position in order to maintain a certain order, especially when it goes against the logic that targets the class based on its position? link.closest('item').classList.add('c-class') // Contrad ...

Is it possible to preserve the <canvas> elements to use for future animation frames?

Currently, I am working on a graph visualization project that involves complex calculations being done on an HTML5 canvas. My goal is to create an interactive animation where the graph remains fixed, but additional elements are overlaid as the mouse moves ...

The fusion of Combining Forms, JSON, AJAX, PHP, and Google graphs

I'm completely new to integrating JScript, Ajax, and Google Graphs. Although I've managed to get each of them working separately, combining them has proven to be quite challenging. Google Graph Part of my code (Form is inactive here): <html& ...

Explore by the anchor tag

I've recently implemented a search bar utilizing Bootstrap. This is the code for the search bar: <div class="md-form mt-0"> <input class="form-control" id="myInput" type="text" placeholder="Sear ...

What is the most effective method to extract an ID from a URL that is written in various formats?

Does anyone know of a reliable method to extract an ID from various URL formats using javascript or jquery? https://plus.google.com/115025207826515678661/posts https://plus.google.com/115025207826515678661/ https://plus.google.com/115025207826515678661 ht ...

typescript error is not defined

While browsing online, I came across a post discussing how to transfer data from an MVC model to a .ts file. The suggestion was to include the following code: <script type="text/javascript"> var testUrl = @Html.Raw(Json.Encode(Model.testUrl) ...

CSS - Achieving full width on hover even when the element has a specified width setting

I am encountering an issue with my CSS. Although I have successfully centered everything, I am facing a problem with the hover effect in CSS. Whenever I apply the active class or hover over an li element, the background color expands to 100%. Additionally, ...

Implementing setInterval in ReactJS to create a countdown timer

I have been working on developing a timer application using React. The functionality involves initiating a setInterval timer when a user clicks a specific button. const [timer, setTimer] = useState(1500) // 25 minutes const [start, setStart] = useState( ...

Identify the absence of search results in an Ajax request to the search page before rendering the HTML content

I am attempting to retrieve JSON code from a page using the following PHP function: private function __ajax_admin_search($username = '') { $result = $this->admin_login->Admin_Username_Ajax($username); $count = count($result); for ...