4

Been messing with this for a while and can't get it right. I'm trying to create arrays for every path from this JSON.

[
  {
    "WebApp : calendar": {
      "count": 3151,
      "next": {
        "ViewWorkout": {
          "count": 521,
          "next": {
            "BeginUserSession": {
              "count": 12,
              "next": {}
            },
            "EditWorkout": {
              "count": 134,
              "next": {}
            },
            "WebApp : expandoOpened": {
              "count": 116,
              "next": {}
            },
            "Mobile : Feed": {
              "count": 2,
              "next": {}
            },
            "WebApp : athleteLoadedFromLibrary": {
              "count": 45,
              "next": {}
            },
            "ViewWorkout": {
              "count": 108,
              "next": {}
            },
            "WebApp : workoutQuickViewTabmapGraphClicked": {
              "count": 18,
              "next": {}
            },
            "DeleteWorkout": {
              "count": 9,
              "next": {}
            },
            "WebApp : headerWorkoutIconClicked": {
              "count": 3,
              "next": {}
            },
            "WebApp : notificationCenterOpened": {
              "count": 14,
              "next": {}
            },
            "WebApp : calendar": {
              "count": 3,
              "next": {}
            },
            "WebApp : workoutQuickViewTabsummaryClicked": {
              "count": 1,
              "next": {}
            },
            "AddWorkout": {
              "count": 8,
              "next": {}
            },
            "DeleteEvent": {
              "count": 1,
              "next": {}
            },
            "ViewWorkoutMapAndGraph": {
              "count": 2,
              "next": {}
            },
            "WebApp : fileUploadMenuOpened": {
              "count": 7,
              "next": {}
            },
            "WebApp : athleteSettingsLoadedFromLibrary": {
              "count": 1,
              "next": {}
            },
            "WebApp : workoutQuickViewTabpowerClicked": {
              "count": 2,
              "next": {}
            },
            "WebApp : distributionChartLoaded": {
              "count": 2,
              "next": {}
            },
            "WebApp : homeViewed": {
              "count": 2,
              "next": {}
            },
            "WebApp : loadNotificationFeedbackLocation": {
              "count": 3,
              "next": {}
            },
            "Mobile : athleteChanged": {
              "count": 1,
              "next": {}
            },
            "WebApp : workoutQuickViewTabheartrateClicked": {
              "count": 2,
              "next": {}
            },
            "WebApp : qvUnitsMenutUpdateUnitsToMetricClicked": {
              "count": 1,
              "next": {}
            },
            "WebApp : goToLastWeek": {
              "count": 4,
              "next": {}
            },
            "WebApp : createWorkoutFromLibrary": {
              "count": 2,
              "next": {}
            },
            "AddEvent": {
              "count": 1,
              "next": {}
            },
            "ViewAthleteList": {
              "count": 1,
              "next": {}
            },
            "WebApp : planLoadedFromLibrary": {
              "count": 2,
              "next": {}
            },
            "WebApp : enterFullScreen": {
              "count": 1,
              "next": {}
            },
            "WebApp : downloadFileClicked": {
              "count": 1,
              "next": {}
            },
            "WebApp : contextMenuOpened": {
              "count": 1,
              "next": {}
            }
          }
        },
        "WebApp : athleteLoadedFromLibrary": {
          "count": 1230,
          "next": {
            "WebApp : calendar": {
              "count": 1190,
              "next": {}
            },
            "WebApp : goToLastWeek": {
              "count": 3,
              "next": {}
            },
            "ViewWorkout": {
              "count": 12,
              "next": {}
            },
            "BeginUserSession": {
              "count": 7,
              "next": {}
            },
            "AddWorkout": {
              "count": 3,
              "next": {}
            },
            "WebApp : athleteLoadedFromLibrary": {
              "count": 7,
              "next": {}
            },
            "WebApp : refreshCalendar": {
              "count": 1,
              "next": {}
            },
            "WebApp : quickViewOpened": {
              "count": 1,
              "next": {}
            },
            "WebApp : notificationCenterOpened": {
              "count": 1,
              "next": {}
            },
            "WebApp : selectCalendarDate": {
              "count": 1,
              "next": {}
            },
            "WebApp : goToNextWeek": {
              "count": 1,
              "next": {}
            },
            "WebApp : createWorkoutFromLibrary": {
              "count": 1,
              "next": {}
            }
          }
        },
        "WebApp : notificationCenterOpened": {
          "count": 276,
          "next": {
            "WebApp : loadNotificationFeedbackLocation": {
              "count": 111,
              "next": {}
            },
            "WebApp : athleteLoadedFromLibrary": {
              "count": 76,
              "next": {}
            },
            "ViewWorkout": {
              "count": 19,
              "next": {}
            },
            "AddEvent": {
              "count": 1,
              "next": {}
            },
            "WebApp : notificationCenterOpened": {
              "count": 9,
              "next": {}
            },
            "AddWorkout": {
              "count": 5,
              "next": {}
            },
            "BeginUserSession": {
              "count": 16,
              "next": {}
            },
            "WebApp : calendar": {
              "count": 3,
              "next": {}
            },
            "WebApp : goToLastWeek": {
              "count": 2,
              "next": {}
            },
            "WebApp : addAthlete": {
              "count": 5,
              "next": {}
            },
            "$campaign_delivery": {
              "count": 1,
              "next": {}
            },
            "Mobile : Feed": {
              "count": 2,
              "next": {}
            },
            "WebApp : createWorkoutFromLibrary": {
              "count": 2,
              "next": {}
            },
            "WebApp : homeViewed": {
              "count": 1,
              "next": {}
            },
            "WebApp : dashboardViewed": {
              "count": 2,
              "next": {}
            },
            "WebApp : athleteSettingsLoadedFromLibrary": {
              "count": 3,
              "next": {}
            },
            "WebApp : calendarLoadedViaLoadDragNDrop": {
              "count": 2,
              "next": {}
            },
            "WebApp : groupLoadedFromLibrary": {
              "count": 1,
              "next": {}
            },
            "WebApp : workoutQuickViewTabpowerClicked": {
              "count": 1,
              "next": {}
            },
            "WebApp : refreshCalendar": {
              "count": 1,
              "next": {}
            },
            "CMS : Download Chart Exchange chart": {
              "count": 1,
              "next": {}
            },
            "WebApp : selectCalendarDate": {
              "count": 1,
              "next": {}
            }
          }
        },
        "WebApp : planLoadedFromLibrary": {
          "count": 24,
          "next": {
            "WebApp : calendar": {
              "count": 23,
              "next": {}
            },
            "AddTrainingPlanWorkout": {
              "count": 1,
              "next": {}
            }
          }
        }
      }
    }
  }
]

The real end goal is to visualize every path with D3, but right now I'm just trying to figure out how to loop through the data and get all possible paths.

Output should look something like this and take into account that their may be more levels of the same structure.

WebApp : calendar (3151) -> ViewWorkout (521) -> BeginUserSession (12)
WebApp : calendar (3151) -> ViewWorkout (521) -> EditWorkout (134)
...
WebApp : calendar (3151) -> WebApp : athleteLoadedFromLibrary (1230) -> WebApp : calendar (731)
Will Luce
  • 1,781
  • 3
  • 20
  • 33
  • See [Access / process (nested) objects, arrays or JSON](http://stackoverflow.com/q/11922383/218196) – Felix Kling Jun 11 '16 at 04:13
  • Look at this answer: http://stackoverflow.com/questions/2203958/jquery-recursive-iteration-over-objects. You need a recursive function that end when 'next' it's empty "next": {} – Klaujesi Jun 12 '16 at 01:47

2 Answers2

8

function rKeys(o) {
  if (!o || typeof o !== 'object') return [];

  const paths = [];
  const stack = [{ obj: o, path: [] }];

  while (stack.length > 0) {
    const { obj, path } = stack.pop();

    if (typeof obj === 'object' && obj !== null) {
      for (const key in obj) {
        stack.push({ obj: obj[key], path: [...path, key] });
      }
    } else {
      paths.push(path);
    }
  }

  return paths;
}

console.log(...rKeys({ x: { y: { z: 1 }, g: { a: 1, b: 2 } } }));
 

the above outputs a list of paths separated by . of your object. You can then access that value by using lodash's get method

const foo = {bar: {baz: "foo"}}
_.get(foo, ["bar", "baz"]) === "foo" // true

so the output of rKeys is useful

Alita
  • 587
  • 1
  • 6
  • 16
  • 1
    Joining keys is not save, imagine f.e. keys containing a `.`. I would simply build a path *array* (which can also be used inside `_.get()`). – DonFuchs Feb 09 '23 at 11:13
2

I think the following snippet does what you wanted.

function getPaths(o, root = "", result = []) {
  var ok = Object.keys(o);
  return ok.reduce((a,k) => { var p = root + k + "(" + o[k].count + ") -> ";
                              Object.keys(o[k].next).length ? getPaths(o[k].next,p,a)
                                                            : a.push(p);
                              return a;
                            },result);
}
var data = [
  {
    "WebApp : calendar": {
      "count": 3151,
      "next": {
        "ViewWorkout": {
          "count": 521,
          "next": {
            "BeginUserSession": {
              "count": 12,
              "next": {}
            },
            "EditWorkout": {
              "count": 134,
              "next": {}
            },
            "WebApp : expandoOpened": {
              "count": 116,
              "next": {}
            },
            "Mobile : Feed": {
              "count": 2,
              "next": {}
            },
            "WebApp : athleteLoadedFromLibrary": {
              "count": 45,
              "next": {}
            },
            "ViewWorkout": {
              "count": 108,
              "next": {}
            },
            "WebApp : workoutQuickViewTabmapGraphClicked": {
              "count": 18,
              "next": {}
            },
            "DeleteWorkout": {
              "count": 9,
              "next": {}
            },
            "WebApp : headerWorkoutIconClicked": {
              "count": 3,
              "next": {}
            },
            "WebApp : notificationCenterOpened": {
              "count": 14,
              "next": {}
            },
            "WebApp : calendar": {
              "count": 3,
              "next": {}
            },
            "WebApp : workoutQuickViewTabsummaryClicked": {
              "count": 1,
              "next": {}
            },
            "AddWorkout": {
              "count": 8,
              "next": {}
            },
            "DeleteEvent": {
              "count": 1,
              "next": {}
            },
            "ViewWorkoutMapAndGraph": {
              "count": 2,
              "next": {}
            },
            "WebApp : fileUploadMenuOpened": {
              "count": 7,
              "next": {}
            },
            "WebApp : athleteSettingsLoadedFromLibrary": {
              "count": 1,
              "next": {}
            },
            "WebApp : workoutQuickViewTabpowerClicked": {
              "count": 2,
              "next": {}
            },
            "WebApp : distributionChartLoaded": {
              "count": 2,
              "next": {}
            },
            "WebApp : homeViewed": {
              "count": 2,
              "next": {}
            },
            "WebApp : loadNotificationFeedbackLocation": {
              "count": 3,
              "next": {}
            },
            "Mobile : athleteChanged": {
              "count": 1,
              "next": {}
            },
            "WebApp : workoutQuickViewTabheartrateClicked": {
              "count": 2,
              "next": {}
            },
            "WebApp : qvUnitsMenutUpdateUnitsToMetricClicked": {
              "count": 1,
              "next": {}
            },
            "WebApp : goToLastWeek": {
              "count": 4,
              "next": {}
            },
            "WebApp : createWorkoutFromLibrary": {
              "count": 2,
              "next": {}
            },
            "AddEvent": {
              "count": 1,
              "next": {}
            },
            "ViewAthleteList": {
              "count": 1,
              "next": {}
            },
            "WebApp : planLoadedFromLibrary": {
              "count": 2,
              "next": {}
            },
            "WebApp : enterFullScreen": {
              "count": 1,
              "next": {}
            },
            "WebApp : downloadFileClicked": {
              "count": 1,
              "next": {}
            },
            "WebApp : contextMenuOpened": {
              "count": 1,
              "next": {}
            }
          }
        },
        "WebApp : athleteLoadedFromLibrary": {
          "count": 1230,
          "next": {
            "WebApp : calendar": {
              "count": 1190,
              "next": {}
            },
            "WebApp : goToLastWeek": {
              "count": 3,
              "next": {}
            },
            "ViewWorkout": {
              "count": 12,
              "next": {}
            },
            "BeginUserSession": {
              "count": 7,
              "next": {}
            },
            "AddWorkout": {
              "count": 3,
              "next": {}
            },
            "WebApp : athleteLoadedFromLibrary": {
              "count": 7,
              "next": {}
            },
            "WebApp : refreshCalendar": {
              "count": 1,
              "next": {}
            },
            "WebApp : quickViewOpened": {
              "count": 1,
              "next": {}
            },
            "WebApp : notificationCenterOpened": {
              "count": 1,
              "next": {}
            },
            "WebApp : selectCalendarDate": {
              "count": 1,
              "next": {}
            },
            "WebApp : goToNextWeek": {
              "count": 1,
              "next": {}
            },
            "WebApp : createWorkoutFromLibrary": {
              "count": 1,
              "next": {}
            }
          }
        },
        "WebApp : notificationCenterOpened": {
          "count": 276,
          "next": {
            "WebApp : loadNotificationFeedbackLocation": {
              "count": 111,
              "next": {}
            },
            "WebApp : athleteLoadedFromLibrary": {
              "count": 76,
              "next": {}
            },
            "ViewWorkout": {
              "count": 19,
              "next": {}
            },
            "AddEvent": {
              "count": 1,
              "next": {}
            },
            "WebApp : notificationCenterOpened": {
              "count": 9,
              "next": {}
            },
            "AddWorkout": {
              "count": 5,
              "next": {}
            },
            "BeginUserSession": {
              "count": 16,
              "next": {}
            },
            "WebApp : calendar": {
              "count": 3,
              "next": {}
            },
            "WebApp : goToLastWeek": {
              "count": 2,
              "next": {}
            },
            "WebApp : addAthlete": {
              "count": 5,
              "next": {}
            },
            "$campaign_delivery": {
              "count": 1,
              "next": {}
            },
            "Mobile : Feed": {
              "count": 2,
              "next": {}
            },
            "WebApp : createWorkoutFromLibrary": {
              "count": 2,
              "next": {}
            },
            "WebApp : homeViewed": {
              "count": 1,
              "next": {}
            },
            "WebApp : dashboardViewed": {
              "count": 2,
              "next": {}
            },
            "WebApp : athleteSettingsLoadedFromLibrary": {
              "count": 3,
              "next": {}
            },
            "WebApp : calendarLoadedViaLoadDragNDrop": {
              "count": 2,
              "next": {}
            },
            "WebApp : groupLoadedFromLibrary": {
              "count": 1,
              "next": {}
            },
            "WebApp : workoutQuickViewTabpowerClicked": {
              "count": 1,
              "next": {}
            },
            "WebApp : refreshCalendar": {
              "count": 1,
              "next": {}
            },
            "CMS : Download Chart Exchange chart": {
              "count": 1,
              "next": {}
            },
            "WebApp : selectCalendarDate": {
              "count": 1,
              "next": {}
            }
          }
        },
        "WebApp : planLoadedFromLibrary": {
          "count": 24,
          "next": {
            "WebApp : calendar": {
              "count": 23,
              "next": {}
            },
            "AddTrainingPlanWorkout": {
              "count": 1,
              "next": {}
            }
          }
        }
      }
    }
  }
],
paths = getPaths(data[0]);
console.log(paths);

You have to call getPaths function with the root object as argument. In you case it would be like getPaths(data[0]); and result will be an array of all paths.

Redu
  • 25,060
  • 6
  • 56
  • 76