How to impose condition on n-tuple?

Is it possible to place some condition over the ements of Vector of Tuples to creat another Vector of Tuples?

For example, I have buch of tuples demonstraing some properties of devices (property1, property2, deice_ID). besides there are two other vectors IDs, and a Super_property vector showing a special property of a device (alaways length(ID) = length( Super_P)) . For instance, device with ID `4` is special only if it has the proprty of `25`. Based o these how to crreate a vector that only returns the special devices?

``````
Devices = [(25, 504, 4), (24, 518, 9) , (20, 250, 7), (29, 248, 4), (29, 283, 4), (22, 528, 9) , (21, 270, 4), (27, 218, 7), (25, 123, 4), (32, 123, 9)]

ID  = [4,7,9]
Super_P = [25, 27, 22]

``````

This is what Iâ€™m looking for:

``````Specials = [ [ (25, 504, 4), (25, 123, 4) ] , (27, 218, 7), (22, 528, 9)]
``````

Something like this?

``````julia> Devices = [(25, 504, 4), (24, 518, 9) , (20, 250, 7), (29, 248, 4), (29, 283, 4), (22, 528, 9) , (21, 270, 4), (27, 218, 7), (28, 123, 4), (32, 123, 9)];
julia> ID  = [4,7,9];
julia> Super_P = [25, 27, 22];

julia> function is_special(device)
prop1, prop2, id = device
i = findfirst(==(id), ID)
return prop1 == Super_P[i]
end
is_special (generic function with 1 method)

julia> filter(is_special, Devices)
3-element Vector{Tuple{Int64, Int64, Int64}}:
(25, 504, 4)
(22, 528, 9)
(27, 218, 7)
``````

Here I used `findfirst` to look for the index of `id` in the `ID` array, and then compare `prop1` to the special value stored at the same index in `Super_P`. (If it is not guaranteed that all possible ids are listed in `ID`, then youâ€™d have to handle the special case where you donâ€™t find the given id in `ID`.)

`filter` is then used to only keep the devices matching the criterion in `Devices`.

2 Likes

This sounds like it would be easier to maintain if you made a struct,

``````struct Device
property_1::Int
property_2::Int
id::Int
end

is_special(d::Device, id, property) = d.id == id && d.property_1 == property

devices = [Device(d...) for d in Devices]

special = [filter(devices) do d
is_special(d, i, p)
end for (i, p) in zip(ID, Super_P)]

``````
3 Likes

@ffevotte, is there an easy way to group the tuples that result from your code?

A laborious way:

``````is_special(device) = device[1] == Super_P[findfirst(==(device[3]), ID)]

sd = filter(is_special, Devices)
ix = getindex.(sd,3)
specials = [sd[ix .== u] for u in unique(ix)]
``````
1 Like

Ah, it looks like the grouping requirement arrived in an edit to the question, after I posted my answerâ€¦ @Kevin_12 please donâ€™t do that: it makes it rather hard to follow threads when posts are substantially modified without warningâ€¦

LGTM.

An other way, probably as laborious as yours

``````is_special(device) = device[1] == Super_P[findfirst(==(device[3]), ID)]
specials = filter(is_special, Devices)
specials_grouped = [filter(d->d[3]==id, specials) for id in ID]
``````

But I do agree with @gustaphe: itâ€™s awkward to manipulate tuples here. Since we know that we are manipulating â€śdevicesâ€ť, itâ€™s best to declare a specific type and use that.

2 Likes
``````fandl=[(first(D),last(D)) for D in Devices]
Devices[[findfirst(isequal(spid), fandl) for spid in zip(Super_P,ID)]]

``````
1 Like

Not at all, your comprehension with a filter inside looks pretty good. Thanks.

1 Like

I just got back to my computer, and Iâ€™m frankly shocked that my phone written solution ran perfectly.

2 Likes

this should do just what is required

``````getindex.([Devices],[findall(isequal(spid), getindex.(Devices, [[1,3]])) for spid in zip(Super_P,ID)])

3-element Vector{Vector{Tuple{Int64, Int64, Int64}}}:
[(25, 504, 4), (25, 123, 4)]
[(27, 218, 7)]
[(22, 528, 9)]
``````
``````filter(t->(t[1],t[3]) in zip(Super_P,ID), Devices)

4-element Vector{Tuple{Int64, Int64, Int64}}:
(25, 504, 4)
(22, 528, 9)
(27, 218, 7)
(25, 123, 4)
``````