1 /** 2 Copyright: Copyright (c) 2018, Joakim Brännström. All rights reserved. 3 Authors: Jacob Carlborg 4 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 5 6 Copied from DStep. 7 8 Convenient functions for a set. 9 */ 10 module dextool.set; 11 12 import std.algorithm : filter; 13 import std.range : ElementType, isOutputRange; 14 15 @safe: 16 17 struct Set(T) { 18 alias Type = void[0][T]; 19 Type data; 20 21 bool opBinaryRight(string op)(T key) if (op == "in") { 22 return (key in data) !is null; 23 } 24 25 bool empty() @safe pure nothrow const @nogc { 26 return data.length == 0; 27 } 28 29 size_t length() @safe pure nothrow const @nogc { 30 return data.length; 31 } 32 33 void add(T value) @safe pure nothrow { 34 data[value] = (void[0]).init; 35 } 36 37 void add(Set!T set) @safe pure nothrow { 38 add(set.data); 39 } 40 41 void add(Type set) @safe pure nothrow { 42 foreach (key; set.byKey) 43 data[key] = (void[0]).init; 44 } 45 46 void add(Range)(Range r) @safe pure nothrow if (is(ElementType!Range == T)) { 47 foreach (v; r) 48 data[v] = (void[0]).init; 49 } 50 51 void remove(T value) { 52 data.remove(value); 53 } 54 55 Set!T clone() @safe pure nothrow { 56 Set!T result; 57 result.add(data); 58 return result; 59 } 60 61 bool contains(T value) { 62 return (value in data) !is null; 63 } 64 65 /** The set difference according to Set Theory. 66 * 67 * It is the set of all members in self that are not members of set. 68 */ 69 Set!T setDifference(Set!T set) { 70 typeof(this) r; 71 foreach (k; toRange.filter!(a => !set.contains(a))) 72 r.add(k); 73 74 return r; 75 } 76 77 /** The symmetric difference according to Set Theory. 78 * 79 * It is the set of all objects that are a member of exactly one of self and set. 80 */ 81 Set!T symmetricDifference(Set!T set) { 82 typeof(this) r; 83 foreach (k; toRange.filter!(a => !contains(a))) 84 r.add(k); 85 foreach (k; toRange.filter!(a => !contains(a))) 86 r.add(k); 87 88 return r; 89 } 90 91 /** The intersection according to Set Theory. 92 * 93 * It is the set of all objects that are members of both self and set. 94 */ 95 Set!T intersect(Set!T set) { 96 97 typeof(this) r; 98 foreach (k; toRange.filter!(a => set.contains(a))) 99 r.add(k); 100 101 return r; 102 } 103 104 auto toArray() { 105 import std.array : appender; 106 107 auto app = appender!(T[])(); 108 foreach (key; toRange) 109 app.put(key); 110 return app.data; 111 } 112 113 auto toRange() inout { 114 return data.byKey; 115 } 116 117 string toString() { 118 import std.array : appender; 119 120 auto buf = appender!string; 121 toString(buf); 122 return buf.data; 123 } 124 125 void toString(Writer)(ref Writer w) const if (isOutputRange!(Writer, char)) { 126 import std.format : formattedWrite; 127 128 formattedWrite(w, "Set!(%s)(%-(%s, %))", T.stringof, toRange); 129 } 130 } 131 132 auto toSet(RangeT)(RangeT range) { 133 import std.traits : Unqual; 134 135 alias T = ElementType!RangeT; 136 137 Set!(Unqual!T) result; 138 foreach (item; range) 139 result.add(item); 140 return result; 141 }