Z24452

{
    "Z1K1": "Z2",
    "Z2K1": {
        "Z1K1": "Z6",
        "Z6K1": "Z24452"
    },
    "Z2K2": {
        "Z1K1": "Z14",
        "Z14K1": "Z24450",
        "Z14K3": {
            "Z1K1": "Z16",
            "Z16K1": "Z600",
            "Z16K2": "function Z24450(Z24450K1, Z24450K2, Z24450K3) {\n    const requested = Z24450K2.map(f =\u003E f.Z6091K1);\n    const requestedSet = new Set(requested);\n\n    const rankedForms = Z24450K1.Z6005K7.map((form, index) =\u003E {\n        const actualSet = new Set(form.Z6004K4.map(f =\u003E f.Z6091K1));\n        const intersectionSize = requested.filter(f =\u003E actualSet.has(f)).length;\n\n        let matchLevel, noise;\n        \n        // form ranking\n\t\tif (intersectionSize === requestedSet.size \u0026\u0026 actualSet.size === requestedSet.size) {            matchLevel = 0;  // sets match (all are \"best\")\n            noise = 0;       // set identity\n        } else if (intersectionSize \u003E 0) {\n            matchLevel = 1;  // subset\n            noise = actualSet.size - intersectionSize;\n        } else {\n            matchLevel = 2;  // disjoint sets\n            noise = actualSet.size;  // (greatest disjunction is worst)\n        }\n\n        const matchVector = requested.map(f =\u003E actualSet.has(f) ? 1 : 0);\n        //use array to conserve order within ranked groups\n\n        return { form, matchLevel, noise, matchVector, index };\n    });\n\n    rankedForms.sort((a, b) =\u003E {\n        if (a.matchLevel !== b.matchLevel) return a.matchLevel - b.matchLevel;\n        if (a.noise !== b.noise) return a.noise - b.noise;\n        for (let i = 0; i \u003C a.matchVector.length; i++) {\n            if (a.matchVector[i] !== b.matchVector[i]) {\n                return b.matchVector[i] - a.matchVector[i];\n            }\n        }\n        return a.index - b.index;\n    });\n\n    const canonicalOrder = [...requested];\n    const seen = new Set(requested);\n    const preferredLangs = Z24450K3.map(lang =\u003E lang.Z60K1);\n\n    const orderedForms = rankedForms.map(({ form }) =\u003E {\n        for (const f of form.Z6004K4) {\n            const id = f.Z6091K1;\n            if (!seen.has(id)) {\n                seen.add(id);\n                canonicalOrder.push(id);\n            }\n        }\n\n        const reps = form.Z6004K3.Z12K1;\n        const sortedReps = [];\n        const usedReps = new Set();\n\n        for (const lang of preferredLangs) {\n            for (const rep of reps) {\n                if (rep.Z11K1.Z60K1 === lang \u0026\u0026 !usedReps.has(rep)) {\n                    sortedReps.push(rep);\n                    usedReps.add(rep);\n                }\n            }\n        }\n        for (const rep of reps) {\n            if (!usedReps.has(rep)) sortedReps.push(rep);\n        }\n\n        const featureMap = new Map(form.Z6004K4.map(f =\u003E [f.Z6091K1, f]));\n        const sortedFeatures = canonicalOrder\n            .filter(id =\u003E featureMap.has(id))\n            .map(id =\u003E featureMap.get(id));\n\n        return {\n            ...form,\n            Z6004K3: { ...form.Z6004K3, Z12K1: sortedReps },\n            Z6004K4: sortedFeatures\n        };\n    });\n\n    return orderedForms;\n}"
        }
    },
    "Z2K3": {
        "Z1K1": "Z12",
        "Z12K1": [
            "Z11",
            {
                "Z1K1": "Z11",
                "Z11K1": "Z1002",
                "Z11K2": "order lexeme forms by features \u0026 lang., JavaScript"
            }
        ]
    },
    "Z2K4": {
        "Z1K1": "Z32",
        "Z32K1": [
            "Z31"
        ]
    },
    "Z2K5": {
        "Z1K1": "Z12",
        "Z12K1": [
            "Z11"
        ]
    }
}