There are a few ways to do this. Any LOS check will use collisions. You can use a raycast/LOS function to see if your LOS hits a solid part of your tilemap or not, and get the layout x/y position and use that to get tile index position and ID. This will only allow you two classes of specific tiles though - solid or not solid.
A workaround is to layer some invisible tilemaps and paint solids where you want them to collide, then you can differentiate which tilemap you are hitting to do different actions.
A third way is to draw invisible placeholder sprites with LOS behaviors. This way is probably the simplest if you don't have very complex shapes or very large maps for collisions, as you won't need a custom LOS function.
For your array question, if you don't want to check every cell, use a nested System "For" loop.
Conditions
For "x" from a to b
--- For "y" from a to b
Expression
Array.At(loopindex("x"),loopindex("y"))
Edit: As for performance impact, I'm actually not sure if there is any different between this and for each x/y with additional conditions such as x>a and y<b or something like that. It is something you can test pretty quickly - if there is a noticeable difference let us know! If you can't tell if there is a difference, don't worry about it.