www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - In Expressions

reply Andrey <andrey kabylin.ru> writes:
Hello, is there any way to using in expression like in python, 
e.g.
 if 4 in [1, 3, 4]:
     do something
My code in D
 if (regionAlign in [RegionAlign.top, RegionAlign.bottom]) {
    ...
 }
throws an error:
 incompatible types for (((cast(Widget)this).regionAlign()) in 
 ([top, bottom])): 'RegionAlign' and 'RegionAlign[]'
Mar 04 2017
next sibling parent reply John Colvin <john.loughran.colvin gmail.com> writes:
On Saturday, 4 March 2017 at 17:11:46 UTC, Andrey wrote:
 Hello, is there any way to using in expression like in python, 
 e.g.
 if 4 in [1, 3, 4]:
     do something
My code in D
 if (regionAlign in [RegionAlign.top, RegionAlign.bottom]) {
    ...
 }
throws an error:
 incompatible types for (((cast(Widget)this).regionAlign()) in 
 ([top, bottom])): 'RegionAlign' and 'RegionAlign[]'
The in operator is defined for associative arrays, but not for normal arrays/slices. You could do this: import std.algorithm : canFind; if ([RegionAlign.top, RegionAlign.bottom].canFind(regionAlign)) { } Consider using only(RegionAlign.top, RegionAlign.bottom) instead of [] to avoid allocating a temporary array. import std.algorithm : canFind; if (only(RegionAlign.top, RegionAlign.bottom).canFind(regionAlign)) { } but to be honest, I would just repeat myself a bit and write if (regionAlign == RegionAlign.top || regionAlign == RegionAlign.bottom) { } If you *really* must have `in`, you could wrap your arrays (or other ranges) in this: import std.range : isInputRange; struct WithInOp(alias eqPred = "a == b", Range) if (isInputRange!Range) { Range range; alias range this; bool opBinaryRight(string op : "in", T)(T rhs) { import std.algorithm.searching : canFind; return range.canFind!eqPred(rhs); } } auto withInOp(alias eqPred = "a == b", Range)(Range range) { return WithInOp!(eqPred, Range)(range); } unittest { auto r = withInOp([1, 2, 4]); assert(1 in r); assert(3 !in r); assert([1, 2] in r); assert([2, 2] !in r); struct S { int main, extra; } auto r2 = withInOp!"a.main == b.main"([S(1, 3), S(2, 4), S(4, 1)]); assert(S(1, 7) in r2); assert(S(3, 4) !in r2); assert([S(2, -42), S(4, 3)] in r2); assert([S(2, -42), S(3, 3)] !in r2); }
Mar 04 2017
parent reply Andrey <andrey kabylin.ru> writes:
On Saturday, 4 March 2017 at 17:57:16 UTC, John Colvin wrote:
 but to be honest, I would just repeat myself a bit and write

 if (regionAlign == RegionAlign.top ||
     regionAlign == RegionAlign.bottom) {
 }
That's exactly what I did, just wondered - how to do such a thing. Thank's for the detailed explanation.
Mar 04 2017
parent Basile B. <b2.temp gmx.com> writes:
On Saturday, 4 March 2017 at 19:31:46 UTC, Andrey wrote:
 On Saturday, 4 March 2017 at 17:57:16 UTC, John Colvin wrote:
 but to be honest, I would just repeat myself a bit and write

 if (regionAlign == RegionAlign.top ||
     regionAlign == RegionAlign.bottom) {
 }
That's exactly what I did, just wondered - how to do such a thing. Thank's for the detailed explanation.
Run this through DUB: ``` /+dub.sdl: name "dub_script" dependency "iz" version="~master" +/ module dub_script; enum RegionAlign { top, botttom, left, right } import iz.enumset; alias Set = EnumSet!(RegionAlign, Set8); void main(string[] args) { with(RegionAlign) { Set set = [top, left]; assert(top in set); assert(left in set); } } ``` iz.enumset.EnumSet seems to be what you need. (assuming Region align is a named enum...)
Mar 05 2017
prev sibling parent Meta <jared771 gmail.com> writes:
On Saturday, 4 March 2017 at 17:11:46 UTC, Andrey wrote:
 Hello, is there any way to using in expression like in python, 
 e.g.
 if 4 in [1, 3, 4]:
     do something
My code in D
 if (regionAlign in [RegionAlign.top, RegionAlign.bottom]) {
    ...
 }
throws an error:
 incompatible types for (((cast(Widget)this).regionAlign()) in 
 ([top, bottom])): 'RegionAlign' and 'RegionAlign[]'
The reason this is disallowed for normal arrays is that finding a key in an array is O(n) while finding a key in an associative array is O(1). Rather than let users unknowingly write code that looks the same but is far slower for arrays, D doesn't allow this. You can use std.algorithm.among, however. import std.algorithm; if (regionAlign.among!(RegionAlign.top, RegionAlign.bottom)) { //etc. }
Mar 04 2017