Modernizing double loops in C#?

In C#, concerning an IEnumerable, is there a better way to handle searching? The code is currently using a double for loop to search in a "radius" around the character.
for (int dx = -radius; dx <= radius; dx++)
{
for (int dy = -radius; dy <= radius; dy++)
{
Vector2 loc = currentLocation + new Vector2(dx, dy);
if (location.Objects.ContainsKey(loc) && location.Objects[loc] is T t)
{
list.Add(t);
}
}
}
for (int dx = -radius; dx <= radius; dx++)
{
for (int dy = -radius; dy <= radius; dy++)
{
Vector2 loc = currentLocation + new Vector2(dx, dy);
if (location.Objects.ContainsKey(loc) && location.Objects[loc] is T t)
{
list.Add(t);
}
}
}
I was thinking something along the lines of: location.Objects is a SerializableDictionary<Vector2, object> Is it possible to use a Where()/Intersects()/Any()/other()? Maybe by testing overlap with a Rectangle? Rectangle bubba = new Rectangle((int)location.X, (int)location.Y, radius, radius); IEnumerable<T> shortlist = location.Objects.Where(?????);
9 Replies
Jimmacle
Jimmacle•4mo ago
is this in some specific engine? what do you expect the maximum radius to be?
Hackswell [SIGS3GV]
Hackswell [SIGS3GV]•4mo ago
Probably no more than 10. It's for a StarewValley mod, but I'm just trying to figure out C# better with this excercise. 🙂
Jimmacle
Jimmacle•4mo ago
the fix would be to store the objects more efficiently to begin with, like in a quadtree but you probably don't have control over that is there an observed performance issue with the current solution?
Hackswell [SIGS3GV]
Hackswell [SIGS3GV]•4mo ago
Or possibly a way to enumerate our "square of coordinates" without the double loop. Nope! 🙂 As I said, I'm just interested in different ways to do this.
Jimmacle
Jimmacle•4mo ago
the double loop in of itself isn't a bad thing, you're going to be searching the same number of cells regardless unless you completely change the search method which would require changing how the engine stores objects
Hackswell [SIGS3GV]
Hackswell [SIGS3GV]•4mo ago
Just thought it might be more readable with some "where" or "in" or "intersect"
Jimmacle
Jimmacle•4mo ago
the only major problem i'd fix is using TryGetValue instead of containskey and indexing so you cut your lookups in half besides that i don't see much point in code golfing with linq
Hackswell [SIGS3GV]
Hackswell [SIGS3GV]•4mo ago
Not the answer to this mental excercise, but thanks for the tip! Much appreciated Jajajajajaja
Landan
Landan•4mo ago
Generate vectors with a generator:
public static IEnumerable<Vector2> ToAreaVectorSetByRadius(this int radius){
Vector2 x1Vector= new (1, 0)
Vector2 y1Vector= new (0,1)
Vector2 theVector = new Vector(-radius, -radius);
for (int dx = -radius; dx < radius; dx++){
for (int dy = -radius; dy <= radius; dy++){
yield return theVector;
theVector = theVector + y1Vector;
}
theVector = theVector + x1Vector;
}
}

//{ ...
Dictionary<Vector2, object> theDictionary = new (){
{ new (){X=2, Y=3}, "what"},
{ new (){X=3, Y=3}, "nothing"}};

IEnumerable<Vector2> theVectorsByRadius = 5.ToAreaVectorSetByRadius();

var theNewSet = theVectors.AsParallel().Where(v => theDictionary.TryGetValue(v, out var item) && item is {}).ToArray();

Console.WriteLine(string.Join(',', theNewSet.AsEnumerable()));

// instead of mutating your object list, I made a separate collection. You can do with it as you wish.
//}
public static IEnumerable<Vector2> ToAreaVectorSetByRadius(this int radius){
Vector2 x1Vector= new (1, 0)
Vector2 y1Vector= new (0,1)
Vector2 theVector = new Vector(-radius, -radius);
for (int dx = -radius; dx < radius; dx++){
for (int dy = -radius; dy <= radius; dy++){
yield return theVector;
theVector = theVector + y1Vector;
}
theVector = theVector + x1Vector;
}
}

//{ ...
Dictionary<Vector2, object> theDictionary = new (){
{ new (){X=2, Y=3}, "what"},
{ new (){X=3, Y=3}, "nothing"}};

IEnumerable<Vector2> theVectorsByRadius = 5.ToAreaVectorSetByRadius();

var theNewSet = theVectors.AsParallel().Where(v => theDictionary.TryGetValue(v, out var item) && item is {}).ToArray();

Console.WriteLine(string.Join(',', theNewSet.AsEnumerable()));

// instead of mutating your object list, I made a separate collection. You can do with it as you wish.
//}
There you go. Linq Golfing.