我一直在使用
System.Linq.Count()
以获得中的元素计数
IEnumerable<T>
这花费了大量的时间。
对于instale,对于十万个元素,它需要几秒钟的时间。
有更好的方法吗?
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MyLib
{
public struct Vec3
{
// Properties for X, Y, Z components of the vector.
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
public double SumComponents()
{
return X + Y + Z;
}
public double DotProduct(Vec3 other)
{
return X * other.X + Y * other.Y + Z * other.Z;
}
public double Norm()
{
return Math.Sqrt(X * X + Y * Y + Z * Z);
}
public double Cosine(Vec3 other)
{
return DotProduct(other) / (Norm() * other.Norm());
}
// A static read-only property representing a zero vector.
public static Vec3 Zero { get; } = new Vec3(0, 0, 0);
public static Vec3 One { get; } = new Vec3(1, 1, 1);
public static Vec3 Multiply(Vec3 left, Vec3 right)
{
return new Vec3(left.X * right.X, left.Y * right.Y, left.Z * right.Z);
}
// Constructor to initialize the vector with X, Y, Z components.
public Vec3(double x, double y, double z)
{
X = x;
Y = y;
Z = z;
}
// Add two vectors.
public static Vec3 operator +(Vec3 a, Vec3 b)
{
return new Vec3(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
}
// Subtract two vectors.
public static Vec3 operator -(Vec3 a, Vec3 b)
{
return new Vec3(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
}
// Negate a vector.
public static Vec3 operator -(Vec3 a)
{
return new Vec3(-a.X, -a.Y, -a.Z);
}
// Multiply vector by a scalar.
public static Vec3 operator *(Vec3 a, double scalar)
{
return new Vec3(a.X * scalar, a.Y * scalar, a.Z * scalar);
}
// Multiply scalar by vector (commutative).
public static Vec3 operator *(double scalar, Vec3 a)
{
return a * scalar;
}
// Divide vector by a scalar.
public static Vec3 operator /(Vec3 a, double scalar)
{
if (scalar == 0)
throw new DivideByZeroException("Cannot divide by zero.");
return new Vec3(a.X / scalar, a.Y / scalar, a.Z / scalar);
}
// Calculate dot product of two vectors.
public static double operator *(Vec3 a, Vec3 b)
{
return Vec3.Dot(a, b);
}
// Calculate Dot product of two Vec3 objects
public double Dot(Vec3 other) => X * other.X + Y * other.Y + Z * other.Z;
public static double Dot(Vec3 a, Vec3 b)
{
return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
}
// Calculate cross product of two vectors.
public static Vec3 operator %(Vec3 a, Vec3 b)
{
return new Vec3(
a.Y * b.Z - a.Z * b.Y,
a.Z * b.X - a.X * b.Z,
a.X * b.Y - a.Y * b.X);
}
// Check if two vectors are equal.
public static bool operator ==(Vec3 a, Vec3 b)
{
return a.X == b.X && a.Y == b.Y && a.Z == b.Z;
}
// Check if two vectors are not equal.
public static bool operator !=(Vec3 a, Vec3 b)
{
return !(a == b);
}
// Override Equals() method for value comparison.
public override bool Equals(object obj)
{
// Instead of direct type check, use 'as' to allow nulls
Vec3 vec = (Vec3) obj;
return vec != null && X == vec.X && Y == vec.Y && Z == vec.Z;
}
// Override GetHashCode() method.
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
// Suitable nullity checks etc, of course :)
hash = hash * 23 + X.GetHashCode();
hash = hash * 23 + Y.GetHashCode();
hash = hash * 23 + Z.GetHashCode();
return hash;
}
}
// Calculate magnitude (length) of the vector.
public double Magnitude()
{
return Math.Sqrt(X * X + Y * Y + Z * Z);
}
public double LengthSquared()
{
return X * X + Y * Y + Z * Z;
}
// Normalize the vector (make it unit length).
public Vec3 Normalize()
{
double magnitude = Magnitude();
if (magnitude == 0)
throw new InvalidOperationException("Cannot normalize a zero vector.");
return this / magnitude;
}
// Calculate distance between two vectors.
public static double Distance(Vec3 a, Vec3 b)
{
return (a - b).Magnitude();
}
// Calculate the angle between two vectors in radians.
public static double Angle(Vec3 a, Vec3 b)
{
double dot = a * b;
double magA = a.Magnitude();
double magB = b.Magnitude();
// Ensure no division by zero
if (magA == 0 || magB == 0)
throw new InvalidOperationException("Cannot calculate the angle with a zero vector.");
double cosTheta = dot / (magA * magB);
// Ensure the value is within -1 and 1 to account for any doubleing point errors
cosTheta = Math.Max(-1, Math.Min(1, cosTheta));
return Math.Acos(cosTheta);
}
// Squared norm of the vector
public double NormSquared()
{
return X * X + Y * Y + Z * Z;
}
public static double DistanceSquared(Vec3 v1, Vec3 v2)
{
double dx = v1.X - v2.X;
double dy = v1.Y - v2.Y;
double dz = v1.Z - v2.Z;
return dx * dx + dy * dy + dz * dz;
}
// Override ToString() for easy debugging and display.
public override string ToString()
{
// Using String.Format instead of string interpolation for compatibility.
return String.Format("({0}, {1}, {2})", X, Y, Z);
}
}
public static class TimeSeriesAnalysisAutoCorrelationMemoryLess
{
public static double AutoCorr(int lag, IEnumerable<Vec3> vectorList)
{
int n = vectorList.Count();//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
if (n == 0 || lag >= n || lag < 0)
throw new ArgumentException($"Lag must be between 0 and {n - 1}, and the list cannot be empty.");
double sum = 0;
for (int i = 0; i < n - lag; i++)
{
var vecA = vectorList.ElementAt(i);
var vecB = vectorList.ElementAt(i+lag);
sum += vecA.Dot(vecB);
}
return sum / (n - lag);
}
public static IEnumerable<double> GetTValues(int maxLag, int vectorCount)
{
int validMaxLag = Math.Min(maxLag, vectorCount - 1); // Ensure maxLag does not exceed n-1
for (int lag = 0; lag <= validMaxLag; lag++)
{
yield return lag;
}
}
public static IEnumerable<double> GetCResults(IEnumerable<Vec3> vectorList, int maxLag, double c0)
{
for (int lag = 0; lag <= maxLag; lag++)
{
double cValue = 0;
try
{
cValue = AutoCorr(lag, vectorList);
}
catch (ArgumentException ex)
{
Console.WriteLine(ex.Message);
yield break; // Exit the loop if an invalid lag is encountered
}
yield return cValue / c0; // Normalization is done here
}
}
public static PairReturn<double> GetAutoCorrelationPoints(IEnumerable<Vec3> vectors, int maxLag)
{
double c0 = AutoCorr(0, vectors); // This is the normalization factor
Console.WriteLine($"Normalization factor: {c0}");
return new PairReturn<double>(GetTValues(maxLag, vectors.Count()), GetCResults(vectors, maxLag, c0));
}
}
}
代码在标记的语句上花费了很长时间。