Published
Edited
Feb 25, 2021
1 star
Insert cell
Insert cell
Insert cell
cities = [
{
"@type": "City",
name: "Graz",
containedInPlace: {
"@type": "Country",
name: "Austria"
}
},
{
"@type": "City",
name: "Moscow",
containedInPlace: {
"@type": "Country",
name: "Russia"
}
}
]
Insert cell
Insert cell
administrativeAreas = [
{
"@type": "Country",
identifier: "AT", // ISO 3166-1 alpha-2 country code
name: {
en: "Austria",
de: "Österreich",
ru: "Австрия",
},
alternateName: {
en: "Republic of Austria",
de: "Republik Österreich",
ru: "Австрийская Республика",
},
containsPlace: {
"@type": "State",
name: {
en: "Styria",
de: "Steiermark",
ru: "Штирия",
},
containsPlace: {
"@type": "City",
name: {
en: "Graz",
de: "Graz",
ru: "Грац"
},
},
},
},
{
"@type": "City",
name: "Moscow", // capital of
containedInPlace: [
{
"@type": "Role",
containedInPlace: {
"@type": "Country",
identifier: "SU",
name: ["Soviet Union", "USSR"]
},
startDate: 1922,
endDate: 1991
},
{
"@type": "Role",
containedInPlace: {
"@type": "Country",
identifier: "RU",
name: ["Russia", "Russian Federation"]
},
startDate: 1991
},
]
}
]
Insert cell
Insert cell
flatten(administrativeAreas);
Insert cell
flatten = (places) => {
const flattenPlaces = new Map();
const flatten = (obj, property = null) => {
let value = obj;
if (property) {
value = obj[property];
}
if (_.isPlainObject(value)) {
const type = value["@type"];
if (type === "Role") {
flatten(value[property]);
} else {
const name = getShortestName(value);
if (!flattenPlaces.has(name)) {
const flattenPlace = {"@type": type, name};
flattenPlaces.set(name, flattenPlace)
}

if (value.containedInPlace) {
flatten(value, "containedInPlace");
}

if (value.containsPlace) {
flatten(value, "containsPlace");
}
}
} else if (_.isArray(value)) {
value.forEach(d => flatten(d, property));
} else {
throw new `Unsupported type: ${typeof value}`;
}
}

flatten(places);
return [...flattenPlaces.values()];
}
Insert cell
_ = require("lodash@4")
Insert cell
getShortestName = (obj, language = "en") => {
return getNames(obj, language)[0];
}
Insert cell
getNames = (obj, language = "en") => {
let names = getText(obj.name, language);
if (obj.alternateName) {
const alternateNames = getText(obj.alternateName, language);
names = _.concat(names, alternateNames)
}
return names.sort((a, b) => a.length - b.length);
}
Insert cell
getText = (value, language = "en") => {
if (_.isString(value)) {
return [value];
} else if (_.isPlainObject(value)) {
const localizedValue = value[language] || value.en || value.de || value.ru;
if (_.isString(localizedValue)) {
return [localizedValue];
} else if (_.isArray(localizedValue)) {
return localizedValue;
} else {
throw `Unsupported localizedValue type: ${typeof localizedValue}`;
}
} else if (_.isArray(value)) {
return value;
} else {
throw `Unsupported value type: ${typeof value}`;
}
}
Insert cell
Insert cell
html`<style>
abbr[title] {
text-underline-position: under; /* 'auto' appears broken (Chrome) */
}
</style>`
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more