Improve an IEnumerable function

T

timor.super

Hi group,

imagine I want to count the number of a word in a text. See my actual
code (don't pay attention to the int factor) :

List<KeyValuePair<string, int>> listThingsToFind = new
List<KeyValuePair<string, int>>();
listThingsToFind.Add(new KeyValuePair<string, int>("error", 10));
listThingsToFind.Add(new KeyValuePair<string, int>("value", 50));
MyCSharp2Class myClass = new MyCSharp2Class(listThingsToFind, data);
foreach (KeyValuePair<int, string> akp in myClass.GetValues())
{
}

///// ............


class MyCSharp2Class
{
private readonly List<KeyValuePair<string, int>> _list;
private readonly string _data;

public MyCSharp2Class(List<KeyValuePair<string, int>>
listThingsToFind, string data)
{
_list = listThingsToFind;
_data = data;
}

public IEnumerable<KeyValuePair<int, string>> GetValues()
{
foreach (KeyValuePair<string, int> aThingToFind in
_list)
{
string savData = _data;
int cpt = 0;
int pos = savData.IndexOf(aThingToFind.Key,
StringComparison.InvariantCultureIgnoreCase);
while (savData.Length > 0 && pos >= 0)
{
cpt++;
savData = savData.Substring(pos +
aThingToFind.Key.Length);
pos = savData.IndexOf(aThingToFind.Key,
StringComparison.InvariantCultureIgnoreCase);
}
yield return new KeyValuePair<int, string>(cpt *
aThingToFind.Value, aThingToFind.Key);
}
}
}

I'm using the yield return functionnality to construct my IEnumerable
object. This is working well, but imagine I have to enum twice,
with :

foreach (KeyValuePair<int, string> akp in myClass.GetValues())
{
}
foreach (KeyValuePair<int, string> akp in myClass.GetValues())
{
}

I'm parsing the data string 2 times, even if I've already done it one
time and there's no need to parse one time more.
I would like to optimize my IEnumerable function, and I had the idea
to construct an intern IEnumerable object (a list for example) to
store the result, and If the result is already stored, return only the
list.

Something like this :

class MyCSharp2Class
{
private readonly List<KeyValuePair<string, int>> _list;
private readonly string _data;
private List<KeyValuePair<int, string>>
_internIenumerable;

public MyCSharp2Class(List<KeyValuePair<string, int>>
listThingsToFind, string data)
{
_list = listThingsToFind;
_data = data;
}

public IEnumerable<KeyValuePair<int, string>> GetValues()
{
if (_internIenumerable == null)
{
_internIenumerable = new List<KeyValuePair<int,
string>>();
foreach (KeyValuePair<string, int> aThingToFind in
_list)
{
string savData = _data;
int cpt = 0;
int pos = savData.IndexOf(aThingToFind.Key,
StringComparison.InvariantCultureIgnoreCase);
while (savData.Length > 0 && pos >= 0)
{
cpt++;
savData = savData.Substring(pos +
aThingToFind.Key.Length);
pos = savData.IndexOf(aThingToFind.Key,
StringComparison.InvariantCultureIgnoreCase);
}
KeyValuePair<int, string> aValue = new
KeyValuePair<int, string>(cpt*aThingToFind.Value, aThingToFind.Key);
_internIenumerable.Add(aValue);
yield return aValue;
}
}
else
return _internIenumerable;
}
}

but, I can't return a list for this function.

Do you have an idea what to do ? Of course, I could store the first
enum in the main function, but that's not my purpose ...

Thanks for your help,

Best regards,
S.
 
R

raylopez99

Hi group,

I would like to optimize my IEnumerable function, and I had the idea
to construct an intern IEnumerable object (a list for example) to
store the result, and If the result is already stored, return only the
list.
}

but, I can't return a list for this function.

Do you have an idea what to do ? Of course, I could store the first
enum in the main function, but that's not my purpose ...


Good luck; I doubt anybody's brave enough to optimize your code, but I
could be wrong.

RL
 
P

Peter Duniho

[...]
public IEnumerable<KeyValuePair<int, string>> GetValues()
{
if (_internIenumerable == null)
{
_internIenumerable = new List<KeyValuePair<int,
string>>();
foreach (KeyValuePair<string, int> aThingToFind in
_list)
{
[...]
}
}
else
return _internIenumerable;
}
}

but, I can't return a list for this function.

Do you have an idea what to do ? Of course, I could store the first
enum in the main function, but that's not my purpose ...

I don't think you need to return the list. You just need to have a
different foreach() loop in the second half of the if() statement that
enumerates the list instead of doing the actual work that is done in the
first half of the if() statement.

Of course, you've still got your O(N^2) algorithm; as I mentioned, you
can cache the results of an O(N^2) algorithm, but that doesn't really
make it "optimal". :)

Pete
 
T

timor.super

oh, you mean something like this ?

public IEnumerable<KeyValuePair<int, string>> GetValues()
{
if (_internIenumerable == null)
{
_internIenumerable = new List<KeyValuePair<int,
string>>();
foreach (KeyValuePair<string, int> aThingToFind in
_list)
{
// do the parsing ...
// add to the internIenumerable
yiel return ...;
}
}
else
foreach (KeyValuePair<int, string> pair in
_internIenumerable)
yield return pair;
}

that can be a good solution, but I have to do a foreach again ...

Thanks for your answer :)



[...]
public IEnumerable<KeyValuePair<int, string>> GetValues()
{
if (_internIenumerable == null)
{
_internIenumerable = new List<KeyValuePair<int,
string>>();
foreach (KeyValuePair<string, int> aThingToFind in
_list)
{
[...]
}
}
else
return _internIenumerable;
}
}
but, I can't return a list for this function.
Do you have an idea what to do ? Of course, I could store the first
enum in the main function, but that's not my purpose ...

I don't think you need to return the list. You just need to have a
different foreach() loop in the second half of the if() statement that
enumerates the list instead of doing the actual work that is done in the
first half of the if() statement.

Of course, you've still got your O(N^2) algorithm; as I mentioned, you
can cache the results of an O(N^2) algorithm, but that doesn't really
make it "optimal". :)

Pete- Masquer le texte des messages précédents -

- Afficher le texte des messages précédents -
 
P

Peter Duniho

oh, you mean something like this ?

public IEnumerable<KeyValuePair<int, string>> GetValues()
{
if (_internIenumerable == null)
{
[...]
}
else
foreach (KeyValuePair<int, string> pair in
_internIenumerable)
yield return pair;
}

Yes. Just like that.
that can be a good solution, but I have to do a foreach again ...

Um, well...yes. You are, after all, enumerating.
Thanks for your answer :)

You're welcome. I hope I didn't disappoint "raylopez99" too much. :)

Pete
 
R

raylopez99

You're welcome. I hope I didn't disappoint "raylopez99" too much. :)


Thanks Pete for answering his question. In the future, when I have a
real hard problem I would appreciate it if you solved it too...

In fact, I have a project for a geneaology database that I'm working
on (just for fun)... if I paint myself into a corner I'll call on you
to complete the code... like a relief pitcher in baseball.... but I
keep the copyright! ;-)

RL
 
P

Peter Duniho

raylopez99 said:
Thanks Pete for answering his question. In the future, when I have a
real hard problem I would appreciate it if you solved it too...

You haven't been paying attention. I don't solve any of the hard
problems around here.

For sure, the one I replied to wasn't hard. In fact, most of the issues
had already been addressed in a separate thread. The last fix that he
was asking about was fairly easy.
In fact, I have a project for a geneaology database that I'm working
on (just for fun)... if I paint myself into a corner I'll call on you
to complete the code... like a relief pitcher in baseball.... but I
keep the copyright! ;-)

See above.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top