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