Drop list if element found in nested list in kotlin - kotlin

Hey I have a huge list coming from server. I am adding some data at top of list. I want to remove data from the list. I have nested list in which I need to find the element in nested list.
fun categoriesList() = listOf(
Categories("21", "physical", listOf(SubTopic("1", "abc"), SubTopic("2", "bjhef"))),
Categories("2211", "mind", listOf(SubTopic("1", "abc"), SubTopic("2", "bjhef"))),
Categories("22131", "motorized", listOf(SubTopic("1", "abc"), SubTopic("2", "bjhef"))),
Categories("2134124", "coordination", listOf(SubTopic("1", "abc"), SubTopic("2", "bjhef"))),
Categories("211243", "animal-supported", listOf(SubTopic("1", "abc"), SubTopic("2", "bjhef"))),
)
Categories.kt
data class Categories(
val id: String? = null, val title: String? = null, val subTopic: List<SubTopic>? = null
)
SubTopic.kt
data class SubTopic(
val id: String? = null, val title: String? = null, var priceId: String? = null
)
main.kt
var categoryList: List<Categories>? = null
fun main() {
categoryList = categoriesList()
categoryList?.add(0, Categories("0", "physical-ktm", listOf(SubTopic("1", "vivek"))))
}
So I want to find title = "Vivek" if that found I want to drop my whole list index 0 element data. Important I only need to check element at index 0. I don't want to iterate whole list. If found the data in index 0 drop it otherwise leave it the iteration. So what is efficient way of doing this in kotlin idiomatic way. Can someone guide me. Thanks
UPDATE
categoryList?.forEachIndexed { index, data->
println("$index index -> $data")
}
console
0 index -> Categories(id=0, title=physical-ktm, subTopic=[SubTopic(id=1, title=vivek, priceId=null)])
1 index -> Categories(id=21, title=physical, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
2 index -> Categories(id=2211, title=mind, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
3 index -> Categories(id=22131, title=motorized, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
4 index -> Categories(id=2134124, title=coordination, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
5 index -> Categories(id=211243, title=animal-supported, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
I only want to search in 0 index of Categories and if title = "vivek" is found in subTopic then I want to drop 0 index from Categories and stop iteration. If data is not found at all in subTopic then I don't won't to iterate whole list of Categories.
After #Tenfour04 suggestion I added this code
var categoryList: MutableList<Categories>? = null
fun main() {
categoryList = categoriesList().toMutableList()
categoryList?.add(0, Categories("0", "physical-ktm", listOf(SubTopic("1", "vivek"))))
println("After Add")
categoryList?.forEachIndexed { index, categories ->
println("$index index -> $categories")
}
val matchingIndex = categoryList?.indexOfFirst { it.subTopic?.first()?.title == "vivek" }
if (matchingIndex != null && matchingIndex >= 0) {
categoryList = categoryList?.mapIndexed { index, it ->
if (index == matchingIndex)
it.copy(subTopic = it.subTopic?.drop(1))
else
it
} as MutableList<Categories>?
}
println("After operation")
categoryList?.forEachIndexed { index, categories ->
println("$index index -> $categories")
}
}
Actual Output
After Add
0 index -> Categories(id=0, title=physical-ktm, subTopic=[SubTopic(id=1, title=vivek, priceId=null)])
1 index -> Categories(id=21, title=physical, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
2 index -> Categories(id=2211, title=mind, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
3 index -> Categories(id=22131, title=motorized, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
4 index -> Categories(id=2134124, title=coordination, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
5 index -> Categories(id=211243, title=animal-supported, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
After operation
0 index -> Categories(id=0, title=physical-ktm, subTopic=[])
1 index -> Categories(id=21, title=physical, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
2 index -> Categories(id=2211, title=mind, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
3 index -> Categories(id=22131, title=motorized, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
4 index -> Categories(id=2134124, title=coordination, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
5 index -> Categories(id=211243, title=animal-supported, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
Expect Output
After Add
0 index -> Categories(id=0, title=physical-ktm, subTopic=[SubTopic(id=1, title=vivek, priceId=null)])
1 index -> Categories(id=21, title=physical, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
2 index -> Categories(id=2211, title=mind, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
3 index -> Categories(id=22131, title=motorized, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
4 index -> Categories(id=2134124, title=coordination, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
5 index -> Categories(id=211243, title=animal-supported, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
After operation
0 index -> Categories(id=21, title=physical, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
1 index -> Categories(id=2211, title=mind, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
2 index -> Categories(id=22131, title=motorized, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
3 index -> Categories(id=2134124, title=coordination, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
4 index -> Categories(id=211243, title=animal-supported, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
I want to remove whole Categoriesobject which is present at index 0.

My understood description of the task: Find the first (and only first) Categories in categoriesList that has a subList whose first SubTopic has a title of "vivek". If it is found, set categoriesList to a new List where the Categories where it was found has been replaced with a new Categories instance whose subList has the matched first SubTopic removed.
If prioritizing clarity, I would use map even though it will copy the list regardless of whether any Categories are modified. And I'd use a Boolean variable to determine whether the search must continue.
var itemFound = false
categoriesList = categoriesList.map {
if (!itemFound && it.subTopic?.first()?.title == "vivek") {
itemFound = true
it.copy(subTopic = it.subTopic?.drop(1))
} else {
it
}
}
If prioritizing performance, I would search using indexOf so I would only create the new list if necessary. But really, if performance is truly this critical we really should be using mutable collections and data classes. That might not be possible if doing list comparisons, of course.
val matchingIndex = categories.indexOfFirst { it.subTopic?.first()?.title == "vivek"}
if (matchingIndex >= 0) {
categoriesList = categoriesList.mapIndexed { index, it ->
if (index == matchingIndex)
it.copy(subTopic = it.subTopic?.drop(1))
else
it
}
}
Edit: based on your new comment, I think this is what you are asking for now. Quite a bit simpler.
if(categoriesList.first().subTopics.orEmpty().any { it.title == “vivek” }) {
categoriesList = categoriesList.drop(1)
}

So if I understand the question correctly, you want to eliminate the first – and only the first – subtopic for each category in categoriesList if its title is "Vivek":
data class SubTopic(
val id: String? = null,
val title: String? = null,
var priceId: String? = null
)
data class Categories(
val id: String? = null,
val title: String? = null,
val subTopic: List<SubTopic>? = null
)
val categoriesList = listOf(
Categories("21", "physical", listOf(SubTopic("1", "abc"), SubTopic("2", "Vivek"))),
Categories("2211", "mind", listOf(SubTopic("1", "Vivek"), SubTopic("2", "bjhef"))),
Categories("22131", "motorized", listOf(SubTopic("1", "abc"), SubTopic("2", "bjhef"))),
Categories("2134124", "coordination", listOf(SubTopic("1", "Vivek"), SubTopic("2", "Vivek"))),
Categories("211243", "animal-supported", listOf(SubTopic("1", "abc"), SubTopic("2", "bjhef"))),
)
var categoryList = categoriesList
.map {
it.copy(subTopic = it.subTopic
?.filterIndexed { index, subTopic -> (index == 0 && subTopic.title != "Vivek") || index > 0 }
)
}
categoryList.forEach(::println)

Related

Sequence Http.get in Elm

Below I have a button that attempts to load remote content ...
import Post exposing (Post)
import Html exposing (..)
import Html.Events exposing (..)
import Http
import Json.Decode as Decode
type alias Model =
{ posts : List Post }
type Msg
= Search String
| PostsReceived (Result Http.Error (List Post))
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Search s ->
let
cmd =
(Decode.list Post.decode)
|> Http.get ("/posts?author=" ++ s)
|> Http.send PostsReceived
in
( model, cmd )
PostsReceived (Ok posts) ->
{ model | posts = posts }
! []
PostsReceived (Err error) ->
( model, Cmd.none )
view : Model -> Html Msg
view model =
button
[ onClick (Search "amelia") ]
[ text "Read posts by Amelia" ]
This is a valid Elm program, only there's one little problem: The API doesn't allow me to search by string. This is not allowed
/posts?author=amelia => Malformed Request Error
However, this is allowed
/posts?author=2 => [ {...}, {...}, ... ]
So I must first fetch an author to get his/her id, and then I can fetch posts using the author's id...
/author?name=amelia => { id: 2, name: "amelia", ... }
/posts?author=2
How can I sequence one request after the next? Ideally I'd like to cache the authors somewhere in the model so we're only requesting ones that we haven't seen before.
You can use Task.andThen to chain two tasks together. Assuming that the /posts response includes the author ID, you can then add that author ID into you model when you handle the response.
Search s ->
let
getAuthor =
Author.decode
|> Http.get ("/author?name=" ++ s)
|> Http.toTask
getPosts author =
(Decode.list Post.decode)
|> Http.get ("/posts?author=" ++ author.id)
|> Http.toTask
cmd =
getAuthor
|> Task.andThen getPosts
|> Task.attempt PostsReceived
in
( model, cmd )
I've got this compiling at https://ellie-app.com/DBJc6Kn3G6a1 if that helps
You can chain together tasks using Task.andThen. You'll first have to convert the web requests to tasks using Http.toTask:
postsByAuthorName : String -> Cmd Msg
postsByAuthorName name =
Http.get ("/author?name=" ++ name) (Decode.field "id" Decode.int)
|> Http.toTask
|> Task.andThen (\id ->
Http.get ("/posts?author=" ++ toString id) (Decode.list decodePost)
|> Http.toTask)
|> Task.attempt PostsReceived
A a dictionary and a couple more Msg options should do it.
You'll have to write the decoder for the Author response, but other than that this should work
type alias Model =
{ posts : List Post
, authors : Dict String Int }
type Msg
= Search String
| SearchAuthor String
| AuthorReceived (Result Http.Error Int String)
| PostsReceived (Result Http.Error (List Post))
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Search author ->
case (Dict.get author model.authors) of
Nothing ->
let
cmd =
(Decode.list Post.decode)
|> Http.get ("/author?name=" ++ author)
|> Http.send AuthorReceived
in
(model,cmd)
Just num ->
let
cmd =
(Decode.list Author.decode)
|> Http.get ("/posts?author=" ++ num)
|> Http.send PostsReceived
in
( model, cmd )
AuthorReceived (Ok number name) ->
let
updatedAuthors = Dict.inster name number model.authors
cmd =
(Decode.list Post.decode)
|> Http.get ("/posts?author=" ++ number)
|> Http.send PostsReceived
in
{model | authors = updatedAuthors } ! [cmd]
AuthorReceived (Err error) ->
(mode, Cmd.none )
PostsReceived (Ok posts) ->
{ model | posts = posts }
! []
PostsReceived (Err error) ->
( model, Cmd.none )
view : Model -> Html Msg
view model =
button
[ onClick (Search "amelia") ]
[ text "Read posts by Amelia" ]

Uncaught TypeError: Cannot read property 'week' of undefined

I'm getting an uncaught typeerror in elm and don't know why.
I'm decoding a json string from an api; the api is giving a list of rostars and each rostar has either a planningId or a flexplanningId. I'd like to map over the list and give each planning a unique id based either on the planningId or the flexplanningId, depending on which it has. Here's the code:
The record definition and the decoders:
type alias Rostar =
{ employee : Employee }
type alias Employee =
{ week : Week
, name : String
, id : Int
, contractHours : Float
}
type alias Week =
{ monday : List Planning
, tuesday : List Planning
, wednesday : List Planning
, thursday : List Planning
, friday : List Planning
, saturday : List Planning
, sunday : List Planning
}
type alias Planning =
{ time : String
, planningId : Maybe Int
, groupId : Int
, groupName : String
, flex : Bool
, employeeTimeslotId : Maybe Int
, flexplanningId : Maybe Int
, employeeId : Maybe Int
, id : Maybe Int
}
responseDecoder : Decoder (List Rostar)
responseDecoder =
list rostarDecoder
rostarDecoder : Decoder Rostar
rostarDecoder =
decode Rostar
|> required "employee" employeeDecoder
employeeDecoder : Decoder Employee
employeeDecoder =
decode Employee
|> required "rostar" weekDecoder
|> required "name" string
|> required "id" int
|> required "contract_hours" float
weekDecoder : Decoder Week
weekDecoder =
decode Week
|> required "monday" (list planningDecoder)
|> required "tuesday" (list planningDecoder)
|> required "wednesday" (list planningDecoder)
|> required "thursday" (list planningDecoder)
|> required "friday" (list planningDecoder)
|> required "saturday" (list planningDecoder)
|> required "sunday" (list planningDecoder)
planningDecoder : Decoder Planning
planningDecoder =
decode Planning
|> required "time" string
|> optional "planning_id" (nullable int) Nothing
|> required "group_id" int
|> required "group_name" string
|> required "flex" bool
|> optional "employee_timeslot_id" (nullable int) Nothing
|> optional "flexplanning_id" (nullable int) Nothing
|> required "employee_id" (nullable int)
|> hardcoded Nothing
The mapping:
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
HandleFeedResponse response ->
let
assignPlanningId : Planning -> Planning
assignPlanningId planning =
case planning.planningId of
Just id ->
{ planning | id = Just (id + 10000000) }
Nothing ->
case planning.flexplanningId of
Just id ->
{ planning | id = Just (id + 90000000) }
Nothing ->
{ planning | id = Nothing }
planningWithId : List Planning -> List Planning
planningWithId day =
List.map assignPlanningId day
mapWeek : Week -> Week
mapWeek week =
{ week
| monday = planningWithId week.monday
, tuesday = planningWithId week.tuesday
, wednesday = planningWithId week.wednesday
, thursday = planningWithId week.thursday
, friday = planningWithId week.friday
, saturday = planningWithId week.saturday
, sunday = planningWithId week.sunday
}
updateResponse : List Rostar
updateResponse =
List.map
(\r ->
let
employee =
{ employee | week = mapWeek employee.week }
in
{ r | employee = employee }
)
response
check =
Debug.log "updatedResponse" updateResponse
in
{ model | rostar = updateResponse } ! []
Here's the error I'm getting:
Uncaught TypeError: Cannot read property 'week' of undefined
Blockquote
Thanks for the help!
I think your problem is caused by the let binding of employee in the updateResponse mapping function. The label employee already exists, so this line is causing a recursive definition.
let
employee =
{ employee | week = mapWeek employee.week }
In Elm 0.18, this is a compile error and gives you a detailed error message rather than leaving the possibility for a runtime error:
Detected errors in 1 module.
-- BAD RECURSION ------------------------------------------------------ Main.elm
employee is defined directly in terms of itself, causing an infinite loop.
132|> employee =
133| { employee | week = mapWeek employee.week }
Maybe you are trying to mutate a variable? Elm does not have mutation, so when I
see employee defined in terms of employee, I treat it as a recursive
definition. Try giving the new value a new name!
Maybe you DO want a recursive value? To define employee we need to know what
employee is, so let’s expand it. Wait, but now we need to know what employee
is, so let’s expand it... This will keep going infinitely!
To really learn what is going on and how to fix it, check out:
https://github.com/elm-lang/elm-compiler/blob/0.18.0/hints/bad-recursion.md
Prior to 0.18, I would see these types of odd "undefined" runtime errors when accidentally performing some kind of unintended recursion. In 0.18, they've added compiler checks for some of the most basic types of problems.
This may not the source of your error,
but your employee-decoder says it needs a rostar variable, which contains a week. Is this correct? Or should it be called week?
Here is the code snippet:
employeeDecoder : Decoder Employee
employeeDecoder =
decode Employee
-- |> required "rostar" weekDecoder -- is this correct?
|> required "week" weekDecoder -- what I would have expected
|> required "name" string
|> required "id" int
|> required "contract_hours" float

Elm 0.17: Task.perform and Maybe

I'm hoping someone could help me with Task.perform as I don't really understand how to handle a Maybe response - and the docs aren't making things clearer for me.
In my model I have results which Maybe a list of items or Nothing.
-- model
type alias Item =
{ name : String}
type alias Model =
{ results : Maybe (List Item) }
model = {
results = Nothing
}
I perform a Task and decode it like so:
-- Task
fetch : String -> Cmd Msg
fetch query =
let url =
"https://some_url" ++ query
in
Task.perform FetchFail FetchSuccess (Http.get decode url)
-- decoder
decoder: Json.Decoder (List Item)
decoder =
Json.at ["data"] (Json.list nestedListDecoder)
-- nestedListDecoder
nestedListDecoder : Json.Decoder Item
nestedListDecoder =
Json.object1 Item
("name" := Json.string)
I then handle the response in update:
-- update
type Msg
= FetchSuccess (Maybe (List Item))
| FetchFail Http.Error
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
FetchSuccess results ->
case results of
Nothing ->
( { model | results = Nothing}, Cmd.none)
Just res ->
( { model | results = res }, Cmd.none)
FetchFail err ->
-- ... handle error
And cater for the Maybe in the view:
-- view
result : Item -> Html Msg
result item =
li [] [ text item.name ]
view : Model -> Html Msg
view model =
ul [ ] (List.map result (Maybe.withDefault [] model.results))
I am getting this error when dealing with Maybe of results.
198| Task.perform FetchFail FetchSuccess (Http.get repos url)
^^^^^^^^^^^^^^^^^^
Function `perform` is expecting the 3rd argument to be:
Task Http.Error (Maybe (List Repo))
But it is:
Task Http.Error (List Repo)
Can anyone advise where else I need to cater for the Maybe ?
A simple tweak to your decoder should fix it. The decoder just needs to use Json.Decode.maybe:
decoder: Json.Decoder (Maybe (List Item))
decoder =
Json.maybe <| Json.at ["data"] (Json.list nestedListDecoder)

Dynamic SQL Parameters with Anorm and Scala Play Framework

Is it possible to dynamically create a list for anorm's "on" method?
I have a form with optional inputs and currently I check each Option and create a list with the defined Options and am trying to pass this through to anorm. Currently I get this compilation error
type mismatch; found : List[java.io.Serializable] required: (Any, anorm.ParameterValue[_])
I'm not sure how I would go about creating this list.
Current code :
val onList = List(
'school_id = input.school,
if(input.rooms isDefined) ('rooms -> input.rooms) else "None" ,
if(input.bathrooms isDefined) ('bathrooms -> input.bathrooms) else "None" ,
if(input.houseType isDefined) ('houseType -> input.houseType) else "None" ,
if(input.priceLow isDefined) ('priceLow -> input.priceLow) else "None" ,
if(input.priceHigh isDefined) ('priceHigh -> input.priceHigh) else "None" ,
if(input.utilities isDefined) ('utilities -> input.utilities) else "None"
).filter(_!="None")
SQL("SELECT * FROM Houses WHERE " + whereString).on(onList).as(sqlToHouse *)
I've tried doing this because initially I thought it would be the same as
.on('rooms -> input.rooms, 'bathroom -> input.bathrooms... etc)
EDIT:
Code is now:
val onList = Seq(
('school_id -> input.school),
if(input.rooms isDefined) ('rooms -> input.rooms.get) else None ,
if(input.bathrooms isDefined) ('bathrooms -> input.bathrooms.get) else None ,
if(input.houseType isDefined) ('houseType -> input.houseType.get) else None ,
if(input.priceLow isDefined) ('priceLow -> input.priceLow.get) else None ,
if(input.priceHigh isDefined) ('priceHigh -> input.priceHigh.get) else None ,
if(input.utilities isDefined) ('utilities -> input.utilities.get) else None
).filter(_!=None).asInstanceOf[Seq[(Any,anorm.ParameterValue[_])]]
using SQL command:
SQL("SELECT * FROM Houses WHERE " + whereString).on(onList:_*).as(sqlToHouse *)
Now getting the exception
[ClassCastException: java.lang.Integer cannot be cast to anorm.ParameterValue]
The important thing is that you have to create values of type ParameterValue.
This is normally done using the toParameterValue() function.
One way would be to create a sequence of Options that you flatten:
val onList = Seq(
Some('school_id -> input.school),
input.rooms.map('rooms -> _),
input.bathrooms.map('bathrooms -> _)
).flatten
This sequence can then be mapped to correct values:
SQL(
"SELECT * FROM Houses WHERE " + whereString
).on(
onList.map(v => v._1 -> toParameterValue(v._2)): _*
)
This can be simplified like this:
val onList = Seq(
Some('school_id -> input.school),
input.rooms.map('rooms -> _),
input.bathrooms.map('bathrooms -> _)
).flatMap(_.map(v => v._1 -> toParameterValue(v._2)))
SQL(
"SELECT * FROM Houses WHERE " + whereString
).on(
onList: _*
)
Or maybe the simplest solution would be this:
val onList = Seq(
Some('school_id -> toParameterValue(input.school)),
input.rooms.map('rooms -> toParameterValue(_)),
input.bathrooms.map('bathrooms -> toParameterValue(_))
).flatten
SQL(
"SELECT * FROM Houses WHERE " + whereString
).on(
onList: _*
)
So I ended up just calling on multiple times.
var query = SQL("SELECT * FROM Houses WHERE " + whereString).on('school_id -> input.school)
if(input.rooms isDefined) query= query.on('rooms -> input.rooms.get)
if(input.bathrooms isDefined) query= query.on('bathrooms -> input.bathrooms.get)
if(input.houseType isDefined) query= query.on('houseType -> input.houseType.get)
if(input.priceLow isDefined) query= query.on('priceLow -> input.priceLow.get)
if(input.priceHigh isDefined) query= query.on('priceHigh -> input.priceHigh.get)
if(input.utilities isDefined) query= query.on('utilities -> input.utilities.get)
query.as(sqlToHouse *)
You can have a look at multivalue parameter is next Anorm (coming Play 2.3/master).

Filtering SPARQL Results

I have following example triples
r1 -> property -> resourceA
r1 -> property -> resourceB
r1 -> property -> resourceC
resourceA -> name -> word1
resourceB -> name -> word2
resourceC -> name -> word4
r2 -> property -> resourceD
r2 -> property -> resourceE
r2 -> property -> resourceF
resourceD -> name -> word1
resourceE -> name -> word2
resourceF -> name -> word3
r3 -> property -> resourceG
r3 -> property -> resourceH
r3 -> property -> resourceI
resourceG -> name -> word5
resourceH -> name -> word6
resourceI -> name -> word7
As parameter i use word1 and word2. I want to get all words incl. word1 and word2, which occurrence with the word1 and word2 together.
The result from this example must be:
word1
word2
word3
word4
I have really no idea, how to make this :(
Assuming the predicate name is the same for all words and there are no other triples with the name predicate:
SELECT DISTINCT ?w {
?s <name> ?w
}
ORDER BY ?w
Edited after the question was edited:
SELECT DISTINCT ?w { # select each word only once
# match three properties under the same resource
?r <property> ?p1, ?p2, ?p3.
# two of the properties must have names "word1" and "word2"
?p1 <name> "word1" .
?p2 <name> "word2" .
# third property name may be anything, including "word1" and "word2"
?p3 <name> ?w .
}
ORDER BY ?w # return words in sorted order