Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

How can I optimize the following code, with LINQ or some other trick?

Bird is a class which has different properties id, name, etc and Nest which is an array of places.

var b = birds as List<Bird> ?? birds.ToList();

    foreach (Bird bs in b)
    {
        for (int i = 0; i< bs.Nest.Count()-1; i++)
        {
            if (bs.Nest[i].X == bs.Nest[i+1].X && bs.Nest[i].Y == bs.Nest[i+1].Y)
            {
                bs.Nest[i + 1].X = null;
                bs.Nest[i + 1].Y = null;
            }

        }
    }
share|improve this question

closed as off-topic by TopinFrassi, JaDogg, Phrancis, Pimgd, Vogel612 Oct 1 '14 at 8:06

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions must involve real code that you own or maintain. Questions seeking an explanation of someone else's code are off-topic. Pseudocode, hypothetical code, or stub code should be replaced by a concrete example." – TopinFrassi, JaDogg, Phrancis
If this question can be reworded to fit the rules in the help center, please edit the question.

1  
LINQ isn't a silver bullet; it's for querying objects; your code is for making an assignment - a "side effect". LINQ queries shouldn't have side effects. You can use LINQ to select the items you want to assign though, and then iterate the results and perform the assignments. Welcome to CR BTW; it would really help if you included definitions for the types involved... –  Mat's Mug Sep 25 '14 at 15:38
3  
Is Bird the word? –  TopinFrassi Sep 25 '14 at 17:30
9  
But really, we need to know the type of birds you are talking about to know what kind of nesting is appropriate. –  200_success Sep 25 '14 at 17:37
3  
@hamsaya Please provide the code of your Bird and Nest class, it will be easier for us to help you –  TopinFrassi Sep 25 '14 at 17:50
2  
Voted to close as "Unclear what you are asking". There's a significant lack of context that could be alleviated by posting the code surrounding this snippet, as well as placing details about the classes Bird and Nest in the question. –  Pimgd Oct 1 '14 at 8:18

2 Answers 2

It would really help if you edited your post to include Bird and Nest classes for context. </rant>


Naming

Before code can be optimized, it needs to be understood. Naming is hard, but good naming is the best way to make your code readable.

Consider calling a cat, a cat bird, a bird:

foreach (Bird bird in birds)
{
    for (int i = 0; i < bird.Nest.Count() - 1; i++)
    {
        if (bird.Nest[i].X == bird.Nest[i + 1].X && bird.Nest[i].Y == bird.Nest[i + 1].Y)
        {
            bird.Nest[i + 1].X = null;
            bird.Nest[i + 1].Y = null;
        }

    }
}

bird is clearer than bs... whatever bs means.


ToList()

var b = birds as List<Bird> ?? birds.ToList();

Given the lack of context, I'm going to make an assumption here, that the method this code is written in is taking a birds parameter, probably of some IEnumerable<Bird> type.

The question is, why do you need a List<Bird> here?

You don't. foreach doesn't need a List<T> to work, and you're not calling any of the List<T>-specific methods - code against interfaces, not implementations. The fact that you "need" to cast to a specific implementation, is a code smell.

I've seen ReSharper recommend this kind of construct when an enumerable was being iterated more than once in a method - which isn't the case here... unless, again, you aren't showing us the whole picture - in which case I'd recommend extracting methods as appropriate, this loop you have here perfectly fits some void ClearAllNests(IEnumerable<Bird>) method.


As for the loop itself, @MarkJohnson's answer uses SelectMany to flatten the nesting, and that's what I would do as well; your if condition becomes a Where condition for each bird's nests.

share|improve this answer
    
I'm not sure about the SelectMany. Wouldn't it make the index-related bit ugly? –  Ben Aaronson Sep 25 '14 at 18:31
3  
@BenAaronson indeed - I'd recommend a different approach, but given there's no definition for the Bird class, I can't. I don't understand the need for indexing nests anyway, I think there should be an IEnumerable<Nest> Nests get-only property on the Bird class, but then again it's hard to recommend anything without more context. –  Mat's Mug Sep 25 '14 at 18:34

This is making some assumptions about your code, and I'm not quite sure what you mean by "optimize", but in some cases, the following is an amusing alternative.

var b = birds as List<Bird> ?? birds.ToList();

foreach (var nextNest in b.SelectMany(bird => (
            from nest in bird.Nest as List<BirdNest> ?? bird.Nest.ToList() 
            let nextNest = bird.Nest[bird.Nest.IndexOf(nest) + 1] 
            where (nest.X == nextNest.X && nest.Y == nextNest.Y)
            select nextNest)))
{
    nextNest.X = null;
    nextNest.Y = null;
}

Update: This is basically a re-statement of the original code, making some assumptions. Again, I'm not sure what you're looking to "optimize", but in some sense this is slightly easier to read, given the new naming and the final action. This can be interpreted slightly more easily as: "for each bird's nest that shares the same location as the previous bird's nest, empty out the nest's coordinates".

It is important to specify what is meant by "optimize". When you use that word, you're simply stating "I wanna make it better," which is not very useful and leaves it up to the reader to make assumptions. Is it slow and you need to speed it up? Does it chew up too much memory? Are you looking to make it more readable and thus more maintainable? You can't simply say "yes" to all of the above because a solution for one will often degrade the solution for your other 2 goals.

As noted in the comments, this chunk of code shares the same defect as the original: it won't work because of the way we iterate through the last item.

share|improve this answer
    
This wouldn't work if there were two nests in the list which which would return true for Nest.Equals –  Ben Aaronson Sep 25 '14 at 18:25
1  
This code won't work as is. When the nest is the last one in the list, trying to access that index plus one will throw and index out of bounds exception. –  tinstaafl Sep 25 '14 at 21:12
    
I believe the issue is the same with the original code. I tried not to make any substantive changes to the code, but only to answer the question, "How can I optimize the following code?" –  Mark Johson Sep 26 '14 at 13:14
3  
Thank you for the guidance on posting responses here. I took my cue for sloppiness from the original quality of the question which contains a defect as well as a poorly defined request for advice. In future responses I'll, perhaps, rise above the quality of the question allowed. –  Mark Johson Sep 26 '14 at 13:30
2  
-1: You've introduced a new bug. i< bs.Nest.Count()-1 In a list of 10 items, indexed 0-9, he stops at 8. You go through each item in the list and refer to the next one with let nextNest = bird.Nest[bird.Nest.IndexOf(nest) + 1]. This will lead to index out of bounds, as noted by tinstaafl. You can claim this is OP's fault but that would be wrong, and for these two reasons you get -1. –  Pimgd Oct 1 '14 at 8:29

Not the answer you're looking for? Browse other questions tagged or ask your own question.