Module:Wikidata/Analyse transitive : Différence entre versions
Ligne 17 : | Ligne 17 : | ||
end | end | ||
end | end | ||
− | return false | + | return false |
end | end | ||
Ligne 28 : | Ligne 28 : | ||
if stopval and (qid == stopval) then | if stopval and (qid == stopval) then | ||
table.insert(olditems, qid) | table.insert(olditems, qid) | ||
− | + | return olditems | |
end | end | ||
if maxnum and (#olditems >= maxnum) then | if maxnum and (#olditems >= maxnum) then | ||
Ligne 40 : | Ligne 40 : | ||
end | end | ||
− | -- recursively adds a list of qid to an existing list, based on the results of a query | + | -- recursively adds a list of qid to an existing list, based on the results of a query |
− | function p.addVals( | + | function p.addVals(list, query, maxdepth, maxnodes, stopval) |
maxdepth = maxdepth or 10 | maxdepth = maxdepth or 10 | ||
maxnodes = maxnodes or 100 | maxnodes = maxnodes or 100 | ||
if (maxdepth < 0) then | if (maxdepth < 0) then | ||
− | return | + | return list |
+ | end | ||
+ | if stopval and alreadyHere(list, stopval) then | ||
+ | return list | ||
end | end | ||
− | + | local origsize = #list | |
− | return | + | for i = 1, origsize do |
+ | -- tried a "checkpos" param instead of starting to 1 each time, but no impact on performance | ||
+ | local candidates = getids(list[i], query) | ||
+ | list = addnewvalues(list, candidates, maxnum, stopval) | ||
+ | if list[#list] == stopval then | ||
+ | return list | ||
end | end | ||
− | + | if #list >= maxnodes then | |
− | + | return list | |
− | |||
− | |||
end | end | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
− | if (#list == | + | if (#list == origsize) then |
return list | return list | ||
end | end | ||
− | return p.addVals(list, query, maxdepth - 1, maxnodes, stopval) | + | return p.addVals(list, query, maxdepth - 1, maxnodes, stopval, origsize + 1) |
end | end | ||
-- returns a list of items transitively matching a query (orig item is not included in the list) | -- returns a list of items transitively matching a query (orig item is not included in the list) | ||
function p.transitiveVals(item, query, maxdepth, maxnodes, stopval) | function p.transitiveVals(item, query, maxdepth, maxnodes, stopval) | ||
+ | maxdepth = maxdepth or 10 | ||
local vals = getids(item, query) | local vals = getids(item, query) | ||
if not vals then | if not vals then | ||
return nil | return nil | ||
end | end | ||
− | + | return p.addVals(vals, query, maxdepth - 1, maxnodes, stopval) | |
end | end | ||
Ligne 91 : | Ligne 91 : | ||
query = {property = 'P279'} | query = {property = 'P279'} | ||
if class == item then -- item is a subclass of itself iff it is a class | if class == item then -- item is a subclass of itself iff it is a class | ||
− | + | if getids(item, query) then | |
− | + | return true | |
− | + | end | |
− | + | return false | |
end | end | ||
return p.inTransitiveVals(class, item, query, maxdepth ) | return p.inTransitiveVals(class, item, query, maxdepth ) | ||
Ligne 105 : | Ligne 105 : | ||
local directclasses = p.transitiveVals(item, {property = 'P31'}, 1) | local directclasses = p.transitiveVals(item, {property = 'P31'}, 1) | ||
if not directclasses then | if not directclasses then | ||
− | + | return false | |
− | end | + | end |
for i, class in pairs(directclasses) do | for i, class in pairs(directclasses) do | ||
if p.isSubclass(targetclass, class, maxdepth - 1) then | if p.isSubclass(targetclass, class, maxdepth - 1) then |
Version du 30 août 2015 à 07:42
La documentation pour ce module peut être créée à Module:Wikidata/Analyse transitive/doc
-- Helpers for queries using transitive properties local p = {} local wd = require "Module:Wikidata" local function getids(item, query) query.excludespecial = true query.displayformat = 'raw' query.entity = item return wd.stringTable(query) end local function alreadyHere(searchset, val) for i, j in pairs(searchset) do if val == j then return true end end return false end -- add new items to a list, avoiding duplicates local function addnewvalues(olditems, newitems, maxnum, stopval) if not newitems then return olditems end for _, qid in pairs(newitems) do if stopval and (qid == stopval) then table.insert(olditems, qid) return olditems end if maxnum and (#olditems >= maxnum) then return olditems end if not alreadyHere(olditems, qid) then table.insert(olditems, qid) end end return olditems end -- recursively adds a list of qid to an existing list, based on the results of a query function p.addVals(list, query, maxdepth, maxnodes, stopval) maxdepth = maxdepth or 10 maxnodes = maxnodes or 100 if (maxdepth < 0) then return list end if stopval and alreadyHere(list, stopval) then return list end local origsize = #list for i = 1, origsize do -- tried a "checkpos" param instead of starting to 1 each time, but no impact on performance local candidates = getids(list[i], query) list = addnewvalues(list, candidates, maxnum, stopval) if list[#list] == stopval then return list end if #list >= maxnodes then return list end end if (#list == origsize) then return list end return p.addVals(list, query, maxdepth - 1, maxnodes, stopval, origsize + 1) end -- returns a list of items transitively matching a query (orig item is not included in the list) function p.transitiveVals(item, query, maxdepth, maxnodes, stopval) maxdepth = maxdepth or 10 local vals = getids(item, query) if not vals then return nil end return p.addVals(vals, query, maxdepth - 1, maxnodes, stopval) end -- returns true if an item is the value of a query, transitively function p.inTransitiveVals(searchedval, sourceval, query, maxdepth, maxnodes ) local vals = p.transitiveVals(sourceval, query, maxdepth, maxnodes, searchedval ) if vals and vals[#vals] == searchedval then return true end return false end -- returns true if an item is a superclass of another, based on P279 function p.isSubclass(class, item, maxdepth) query = {property = 'P279'} if class == item then -- item is a subclass of itself iff it is a class if getids(item, query) then return true end return false end return p.inTransitiveVals(class, item, query, maxdepth ) end -- returns true if one of the best ranked P31 values of an item is the target or a subclass of the target -- rank = 'valid' would seem to make sense, but it would need to check for date qualifiers as some P31 values have begin or end date function p.isInstance(targetclass, item, maxdepth) maxdepth = maxdepth or 10 local directclasses = p.transitiveVals(item, {property = 'P31'}, 1) if not directclasses then return false end for i, class in pairs(directclasses) do if p.isSubclass(targetclass, class, maxdepth - 1) then return true end end return false end return p