// Create from expressions and heading
        public static OrderedIndex Create(ExpressionBlock[] exprs, DataHeading heading)
        {
            var seginfo = exprs.Select(e => new SegmentInfo {
                datatype   = e.ReturnType,
                descending = e.IsDesc,
                grouped    = e.IsGrouped,
                columnno   = heading.FindIndex(e.ToDataColumn()),
            }).ToArray();

            return(Create(seginfo));
        }
        // Transform with ordered calculations - different algorithm
        // 1. Build index
        // 2. Read input file using index
        // 3. Transform and write output file
        public override DataTable TransformOrdered(DataHeading newheading, ExpressionEval[] exprs, ExpressionEval[] orderexps)
        {
            Logger.WriteLine(4, "TransformOrdered {0} exprs={1},{2}", newheading, exprs.Count(), orderexps.Count());

            var numacc   = exprs.Where(e => e.HasFold).Sum(e => e.AccumCount);
            var newtable = DataTableLocal.Create(newheading);
            var newexprs = newtable.Heading.Reorder(exprs);
            var ordidx   = OrderedIndex.Create(orderexps, Heading);
            // list of indexes of not-folded columns
            var notfold = exprs.Where(e => !e.HasFold)
                          .Select(e => newheading.FindIndex(e.Name)).ToArray();

            // Build index
            for (var ord = 0; ord < Cardinality; ++ord) //TODO:Enumerable
            {
                ordidx.Add(GetRow(ord), ord);
            }
            AccumulatorBlock accblk = null;

            // Read in index order, with access to ordering info
            DataRow lastrow = null;

            foreach (var ord in ordidx.RowOrdinals)
            {
                var oldrow = _rows[ord];
                oldrow.OrderedIndex = ordidx; // so row functions can access it
                // if there is a group break, reset the accumulators
                if (ordidx.IsBreak)
                {
                    accblk = AccumulatorBlock.Create(numacc);
                }
                DataRow newrow = oldrow.TransformAggregate(newheading, accblk, newexprs);

                // save the current row, output it on group break or when any non-fold column has changed
                // any rows not output will have identical non-fold cols so only running sums are lost
                var nfchg = (lastrow != null && !notfold.All(x => newrow.Values[x].Equals(lastrow.Values[x])));
                if (nfchg || (lastrow != null && ordidx.IsBreak))
                {
                    newtable.AddRaw(lastrow);
                }
                lastrow = newrow; // guaranteed to be different!
            }
            if (lastrow != null)
            {
                newtable.AddRaw(lastrow);
            }
            Logger.WriteLine(4, "[{0}]", newtable);
            return(newtable);
        }
 // Make an index (on this) where to find our fields in another heading
 // missing fields are -1
 public int[] MakeIndex(DataHeading other)
 {
     return(Enumerable.Range(0, this.Degree)
            .Select(x => other.FindIndex(Columns[x]))
            .ToArray());
 }
Exemple #4
0
        // Create a row that belongs to a table.
        // Can be called with a tuple or non-tuple heading. If the latter, reorder values to match tuple heading.
        public static DataRow Create(DataHeading heading, TypedValue[] values)
        {
            if (values.Length != heading.Degree)
            {
                throw new ArgumentOutOfRangeException("values", "wrong degree");
            }
            Logger.Assert(values.All(v => v != null), "null value");
            var newheading = (heading.IsTuple) ? heading : DataTypeTuple.Get(heading).Heading;
            var dr         = new DataRow()
            {
                DataType = DataTypeTuple.Get(heading),
                Heading  = newheading,
                _values  = (heading.IsTuple) ? values : newheading.Columns.Select(c => values[heading.FindIndex(c)]).ToArray(),
            };

            dr._hashcode = dr.CalcHashCode();
            dr.Heading.CheckValues(dr.Values);
            return(dr);
        }