0

I have a list of Buttons and I want to get the two elements that are 'equal':

for (int i = 0; i < Memory.Count; i++ )
{
     piezas = Memory.FindAll(s => (s.Name != Memory[i].Name && Utilidades.CompareImage(s.Image, Memory[i].Image)));
}

This is supposed (if I'm not wrong) the list with the two elements that have different Name but are using the same Image. I'm more than sure that such elements exists... but I don't know why this doesn't work.

"Utilidades.CompareImage" is an static method:

public static bool CompareImage(Image firstImage, Image secondImage)
        {
            MemoryStream ms = new MemoryStream();
            firstImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
            String firstBitmap = Convert.ToBase64String(ms.ToArray());
            ms.Position = 0;

                secondImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
            String secondBitmap = Convert.ToBase64String(ms.ToArray());

            if (firstBitmap.Equals(secondBitmap))
                return true;
            else
                return false;
        }

I've tested the method before and it's working as intented.

Can you please help me?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • How are you checking the result of your code? Try to add some debug statements showing intermediate results. The code looks like 'it might just work'... – The Nail Jan 21 '12 at 22:07
  • Using breakpoints and the var is NEVER 2 and it should be unless my predicate is wrong. –  Jan 21 '12 at 22:13
  • Well it should be 'a list of two elements', not 2. – The Nail Jan 21 '12 at 22:15
  • Yes, you are right. I wasn't comparing 'var == 2' but instead 'var.Count == 2'. But I'm not specifying things correctly. Sorry about that. –  Jan 21 '12 at 22:17
  • Ok, edit the question. "Expected=2, Actual=..." – H H Jan 21 '12 at 22:22
  • BTW I removed the linq tag because .FindAll is not a linq extension. See also http://stackoverflow.com/questions/1938204/linq-where-vs-findall – The Nail Jan 21 '12 at 22:26
  • Ah indeed you should expect only one element, not two, as pad mentions. – The Nail Jan 21 '12 at 22:39

2 Answers2

1

The code

for (int i = 0; i < Memory.Count; i++ )
{
    var piezas = Memory.FindAll(s => (s.Name != Memory[i].Name 
          && Utilidades.CompareImage(s.Image, Memory[i].Image)));
}

creates a new 'piezas' every time and then doesn't use it.
Also you are checking all combinations twice.

So do you want to find all pairs, the first pair or maybe something in between?

A quick fix, but far from perfect,

for (int i = 0; i < Memory.Count; i++ )
{
    var piezas = Memory.FindAll(s => (s.Name != Memory[i].Name 
          && Utilidades.CompareImage(s.Image, Memory[i].Image)));

    if (piezas.Count > 0)
    {
        // use piezas[0] somehow
        break;
    }
}
H H
  • 263,252
  • 30
  • 330
  • 514
  • Yes, I'm really sorry for not stating that. I just want the first pair, (and I use 'piezas' after, but I didn't copy that because It is not relevant. –  Jan 21 '12 at 22:16
  • Then don't mislead by declaring it with `var` either. – H H Jan 21 '12 at 22:18
  • Hi, thanks, but I was using that. It just that piezas.Count is never two. Is my FindAll 'query' right? –  Jan 21 '12 at 22:21
  • 2
    `piezas.Count = 1` means you found a similar element with `Memory[i]`. So it is totally correct. – pad Jan 21 '12 at 22:29
1

It seems no one mentioned SelectMany yet:

var pieza = Memory.SelectMany((m, i) => 
Memory.Where((m2, j) => i < j && m.Name != m2.Name && 
Utilidades.CompareImage(m.Image, m2.Image))
.Select(m2 => Tuple.Create(m, m2))).First();

if you want all pairs, not just one, replace the final First() call to ToList() or something like that.

user1096188
  • 1,809
  • 12
  • 11