private Cube <UValue> collapse <UValue>(Dimension dimension, Func <Group <TValue>, UValue> aggregator) { IEnumerable <Dimension> dimensions = keyLookup.Keys.Where(otherDimension => dimension != otherDimension).ToArray(); Dictionary <Key, Group <TValue> > lookup = new Dictionary <Key, Group <TValue> >(); foreach (KeyValuePair <Key, TValue> pair in valueLookup) { KeyPart oldKeyPart = pair.Key.GetKeyPart(dimension); IEnumerable <KeyPart> newKeyParts = dimensions.Select(item => pair.Key.GetKeyPart(item)); Key newKey = new Key(newKeyParts, true); Group <TValue> group; if (lookup.ContainsKey(newKey)) { group = lookup[newKey]; } else { group = new Group <TValue>(newKey); lookup.Add(newKey, group); } group.AddPair(oldKeyPart, pair.Value); } LookupBuilder <UValue> builder = new LookupBuilder <UValue>(dimensions); foreach (KeyValuePair <Key, Group <TValue> > pair in lookup) { UValue value = aggregator(pair.Value); builder.Add(pair.Key, value); } return(new Cube <UValue>(builder)); }
private static Cube <UValue> resolvingMerge <UValue>(IEnumerable <Dimension> dimensions, IEnumerable <Cube <TValue> > cubes, Func <Collision <TValue>, UValue> combiner) { Dictionary <Key, Collision <TValue> > lookup = new Dictionary <Key, Collision <TValue> >(); foreach (Cube <TValue> cube in cubes) { foreach (KeyValuePair <Key, TValue> pair in cube.valueLookup) { Collision <TValue> collisions; if (lookup.ContainsKey(pair.Key)) { collisions = lookup[pair.Key]; } else { collisions = new Collision <TValue>(pair.Key); lookup.Add(pair.Key, collisions); } collisions.Add(pair.Value); } } LookupBuilder <UValue> builder = new LookupBuilder <UValue>(dimensions); foreach (Collision <TValue> collision in lookup.Values) { UValue value = combiner(collision); builder.Add(collision.Key, value); } return(new Cube <UValue>(builder)); }
/// <summary> /// Creates a new cube by applying an operation to every value in the cube. /// </summary> /// <typeparam name="UValue">The type of the values after the application.</typeparam> /// <param name="converter">The function for creating a UValue from a TValue.</param> /// <returns>A new cube holding the results of the application to every value in the cube.</returns> public Cube <UValue> Convert <UValue>(Func <TValue, UValue> converter) { if (converter == null) { throw new ArgumentNullException("applicator"); } LookupBuilder <UValue> builder = new LookupBuilder <UValue>(keyLookup.Keys); foreach (KeyValuePair <Key, TValue> pair in this.valueLookup) { UValue value = converter(pair.Value); builder.Add(pair.Key, value); } return(new Cube <UValue>(builder)); }
/// <summary> /// Creates a cube with a single value associated with all of the key parts. /// </summary> /// <param name="key">The key of the singleton.</param> /// <param name="value">The singleton value.</param> /// <returns>A new cube with a single key/value pair.</returns> public static Cube <TValue> Singleton(Key key, TValue value) { if (key == null) { throw new ArgumentNullException("The key must not be null."); } if (key.DimensionCount == 0) { return(NullCube); } IEnumerable <Dimension> dimensions = key.GetKeyParts().Select(part => part.Dimension); LookupBuilder <TValue> builder = new LookupBuilder <TValue>(dimensions); builder.Add(key, value); return(new Cube <TValue>(builder)); }
private static Cube <TValue> merge(IEnumerable <Dimension> dimensions, IEnumerable <Cube <TValue> > cubes) { LookupBuilder <TValue> lookup = new LookupBuilder <TValue>(dimensions); foreach (Cube <TValue> cube in cubes) { foreach (KeyValuePair <Key, TValue> pair in cube.valueLookup) { if (lookup.ContainsKey(pair.Key)) { throw new InvalidOperationException("Two or more cubes had the same key."); } lookup.Add(pair.Key, pair.Value); } } return(new Cube <TValue>(lookup)); }
/// <summary> /// Creates a copy of the cube, excluding values whose keys have a matching key part value. /// </summary> /// <param name="keyPart">The dimension and key value of items to be removed.</param> /// <returns>A new cube where the values matching the key part have been removed.</returns> public Cube <TValue> Exclude(KeyPart keyPart) { if (keyPart == null) { throw new ArgumentNullException("keyPart"); } if (!keyLookup.ContainsKey(keyPart.Dimension)) { throw new ArgumentException("Cannot filter by a dimension that is not in the cube.", "dimension"); } LookupBuilder <TValue> builder = new LookupBuilder <TValue>(keyLookup.Keys); foreach (KeyValuePair <Key, TValue> pair in valueLookup) { if (!keyPart.Equals(pair.Key.GetKeyPart(keyPart.Dimension))) { builder.Add(pair.Key, pair.Value); } } return(new Cube <TValue>(builder)); }
/// <summary> /// Creates a new cube where the key part value in the specified dimension equals the given key part's value. /// </summary> /// <param name="keyPart">The value the keys in the given dimension must equal.</param> /// <returns>A new cube where the keys in the specified dimension equal the given value.</returns> public Cube <TValue> Splice(KeyPart keyPart) { if (keyPart == null) { throw new ArgumentNullException("keyPart"); } if (!keyLookup.ContainsKey(keyPart.Dimension)) { throw new ArgumentException("Cannot splice a dimension that does not exist in the cube", "dimension"); } Dictionary <KeyPart, List <Key> > dimensionLookup = keyLookup[keyPart.Dimension]; LookupBuilder <TValue> builder = new LookupBuilder <TValue>(keyLookup.Keys); List <Key> keys; if (dimensionLookup.TryGetValue(keyPart, out keys)) { foreach (Key key in keys) { TValue value = valueLookup[key]; builder.Add(key, value); } } return(new Cube <TValue>(builder)); }
/// <summary> /// Creates a cube with a new dimension where all the values from the current cube are associated with the given key part value. /// </summary> /// <param name="keyPart">The dimension/key value pair to append to the cube.</param> /// <returns>A new cube with the added dimension and values.</returns> public Cube <TValue> AddDimension(KeyPart keyPart) { if (keyPart == null) { throw new ArgumentNullException("keyPart"); } if (keyLookup.ContainsKey(keyPart.Dimension)) { throw new ArgumentException("The given dimension already exists.", "dimension"); } List <Dimension> dimensions = keyLookup.Keys.ToList(); dimensions.Add(keyPart.Dimension); LookupBuilder <TValue> builder = new LookupBuilder <TValue>(dimensions); foreach (KeyValuePair <Key, TValue> pair in valueLookup) { List <KeyPart> keyParts = new List <KeyPart>(pair.Key.GetKeyParts()); keyParts.Add(keyPart); Key newKey = new Key(keyParts, true); builder.Add(newKey, pair.Value); } return(new Cube <TValue>(builder)); }