List<String>. Replace

S

shapper

Hello,

I have a List<String> and I need to find if it contains "image/pjpeg".
If yes then replace it by "image/jpeg".

What is the best way to do this? I can use Contains but how to replace
that particular item?

Thanks,
Miguel
 
K

Konrad Neitzel

Hi Shapper!

I have a List<String> and I need to find if it contains "image/pjpeg".
If yes then replace it by "image/jpeg".
What is the best way to do this? I can use Contains but how to replace
that particular item?

I would use something like:
place = MyList.IndexOf(ItemToSearchFor);
if (place >= 0)
{
MyList.RemoveAt(place);
MyList.Insert(place, newItemToInsert);
}

Maybe someone else finds some nice code with LINQ or so - But at least
this is a straight forward code that should work (not tested!).

Konrad
 
P

Peter Duniho

Konrad said:
Hi Shapper!




I would use something like:
place = MyList.IndexOf(ItemToSearchFor);
if (place >= 0)
{
MyList.RemoveAt(place);
MyList.Insert(place, newItemToInsert);
}

Note that a) the above only handles a single instance of the string in
the list (may or may not be fine), and b) the above involved three O(n)
operations, when one O(n) and one O(1) operation would suffice:

for (int i = 0; i < MyList.Count; i++)
{
if (MyList == "image/pjpeg")
{
MyList = "image/jpeg";

// break; here if only want to find one instance
}
}
Maybe someone else finds some nice code with LINQ or so - But at least
this is a straight forward code that should work (not tested!).

If a loop over a collection is involved, LINQ can almost always be
forced to do the work. But I'd agree with you that in this case, it
wouldn't add anything useful to the implementation to use LINQ.

Pete
 
F

Family Tree Mike

shapper said:
Hello,

I have a List<String> and I need to find if it contains "image/pjpeg".
If yes then replace it by "image/jpeg".

What is the best way to do this? I can use Contains but how to replace
that particular item?

Thanks,
Miguel
.

This looks more like an issue that should have been (or should be) caught on
validation of things going into the list. Catching each variation as they
come out of a list seems pointless.

Mike
 
V

vanderghast

and without explicit loop:

List<foo> toto = new List<foo>( );
toto.Add(new foo("bozo", 1));
toto.Add(new foo("image/pjpeg", 2));
toto.Add(new foo("bozo", 3));
toto.Add(new foo("image/pjpeg", 4));

toto.FindAll(x => 0 == String.Compare(x.name,
"image/pjpeg")).ForEach(x => x.name = "image/jpeg");


with, as example

class foo
{
public String name;
public decimal other;
public foo(String name, decimal what)
{
this.name = name;
other = what;
}
}


Sure, I ... changed ... the initial problem... because it does NOT work
with List<String> ! (I don't know why, though).


Vanderghast, Access MVP



Peter Duniho said:
Konrad said:
Hi Shapper!




I would use something like:
place = MyList.IndexOf(ItemToSearchFor);
if (place >= 0)
{
MyList.RemoveAt(place);
MyList.Insert(place, newItemToInsert);
}

Note that a) the above only handles a single instance of the string in the
list (may or may not be fine), and b) the above involved three O(n)
operations, when one O(n) and one O(1) operation would suffice:

for (int i = 0; i < MyList.Count; i++)
{
if (MyList == "image/pjpeg")
{
MyList = "image/jpeg";

// break; here if only want to find one instance
}
}
Maybe someone else finds some nice code with LINQ or so - But at least
this is a straight forward code that should work (not tested!).

If a loop over a collection is involved, LINQ can almost always be forced
to do the work. But I'd agree with you that in this case, it wouldn't add
anything useful to the implementation to use LINQ.

Pete
 
P

Peter Duniho

vanderghast said:
[...]
Sure, I ... changed ... the initial problem... because it does NOT work
with List<String> ! (I don't know why, though).

It doesn't work with List<string> because your solution isn't modifying
the list object itself (as needed by the OP). It's modifying individual
objects referenced by the list.

Your solution isn't actually LINQ, but it uses List<T> members that
could be thought of LINQ predecessors. As such, it's "LINQ-like". :)

A LINQ solution that would address the OP's needs would look more like this:

List<string> list = ...;

list.Aggregate(0, (i, x) =>
{
if (x == "image/pjpeg")
{
list = "image/jpeg";
}

return i + 1;
});

As you can see, it's so wordy that it's hardly any better than an
explicit loop. But the real fatal flaw is that because Aggregate() is
using the IEnumerable<string> from the list, once you try to modify an
element of the list, the attempt to retrieve the next element fails with
an exception.

Sticking with the List<T> members, as in your example, you still wind up
with something like this:

List<string> list = ...;
int i = 0;

list.ForEach(x =>
{
if (x == "image/pjpeg")
{
list = "image/jpeg";
}

i++;
});

This avoids the exception, because the ForEach() method iterates through
the list elements explicitly and does not care if you modify the
collection while it's doing that.

But, the syntax really isn't any better than an explicit loop, even so.

Pete
 
A

Arne Vajhøj

I have a List<String> and I need to find if it contains "image/pjpeg".
If yes then replace it by "image/jpeg".

What is the best way to do this? I can use Contains but how to replace
that particular item?

That can be done in many ways.

One is:

lst = lst.ConvertAll<string>(s => s=="image/pjpeg" ? "image/jpeg" : s);

Arne
 
P

Peter Duniho

Arne said:
That can be done in many ways.

One is:

lst = lst.ConvertAll<string>(s => s=="image/pjpeg" ? "image/jpeg" : s);

That doesn't meet the original problem statement. In particular, it
replaces the _entire list_, not the individual elements that need changing.

This subtle difference has significant implications, assuming the
original problem statement was correct. That is, any other code that
still references the original list will fail to see any change to the
list elements. Only the newly created list will have the new elements.

Pete
 
K

Konrad Neitzel

Hi Peter!

Peter Duniho said:
Konrad Neitzel wrote:
Note that a) the above only handles a single instance of the string in
the list (may or may not be fine), and
Yes, but it wasn't clear to me if all entries should be changed or just
one. Adding a while loop is nothing hard...
b) the above involved three O(n) operations, when one O(n) and one
O(1) operation would suffice:
for (int i = 0; i < MyList.Count; i++)
{
if (MyList == "image/pjpeg")
{
MyList = "image/jpeg";

// break; here if only want to find one instance
}
}


And you are right, that it is much better to get rid of one call of
complexity O(n).
Thank you for the correction.

With kind regards,

Konrad
 
G

Göran Andersson

shapper said:
Hello,

I have a List<String> and I need to find if it contains "image/pjpeg".
If yes then replace it by "image/jpeg".

What is the best way to do this? I can use Contains but how to replace
that particular item?

Thanks,
Miguel

Use IndexOf to get the position of the item:

int index = list.IndexOf("image/pjpeg");
if (index != -1) {
list[index] = "image/jpeg";
}

To find multiple items:

int index = list.IndexOf("image/pjpeg");
while (index != -1) {
list[index] = "image/jpeg";
index = list.IndexOf("image/pjpeg", index + 1);
}

You can also use LINQ mehtods:

list = list.Select(s => s == "image/pjpeg" ? "image/jpeg" : s).ToList();

However, this will create a completely new list with the strings
replaced, so it's less efficient.
 
V

vanderghast

That does not generate an error but does not change the elements in the list
either. At least, with:


List<String> tata = new List<string>();
tata.Add("image/pjpeg");
tata.Add("bozo");
tata.Add("image/pjpeg");
tata.Add("bozo");
tata.ConvertAll<string>(s => s == "image/pjpeg" ? "image/jpeg" :
s);

System.Diagnostics.Debug.Assert(tata[0] == "image/jpeg",
"convert fail");



the assertion fails.



Vanderghast, Access MVP
 
G

Guss Davey

Dim SurveyOptionList As New List(Of SurveyOptionInfo)
SurveyOptionList = SurveyOptionController.GetSurveyOptions(objSurvey.SurveyId)
For i As Integer = 0 To SurveyOptionList.Count - 1
If SurveyOptionList.Item(i).OptionName.IndexOf("]") > 0 Then
SurveyOptionList.Item(i).OptionName = ReplaceImageTokens(SurveyOptionList.Item(i).OptionName)
End If
Next

---------------

Private Function ReplaceImageTokens(ByVal strInput As String) As String
Dim strOut As String = strInput
Dim path As String = ControlPath.ToString & "Images/"
strOut = strOut.Replace("[APPROVED]", "<img align=""middle"" src=""" & path & "approved.png"">")
strOut = strOut.Replace("[CHECKMARK]", "<img align=""middle"" src=""" & path & "checkmark.png"">")
Return strOut
End Function
Hello,

I have a List<String> and I need to find if it contains "image/pjpeg".
If yes then replace it by "image/jpeg".

What is the best way to do this? I can use Contains but how to replace
that particular item?

Thanks,
Miguel
On Tuesday, February 16, 2010 1:21 PM Konrad Neitzel wrote:
Hi Shapper!




I would use something like:
place = MyList.IndexOf(ItemToSearchFor);
if (place >= 0)
{
MyList.RemoveAt(place);
MyList.Insert(place, newItemToInsert);
}

Maybe someone else finds some nice code with LINQ or so - But at least
this is a straight forward code that should work (not tested!).

Konrad
Note that a) the above only handles a single instance of the string in
the list (may or may not be fine), and b) the above involved three O(n)
operations, when one O(n) and one O(1) operation would suffice:

for (int i = 0; i < MyList.Count; i++)
{
if (MyList == "image/pjpeg")
{
MyList = "image/jpeg";

// break; here if only want to find one instance
}
}


If a loop over a collection is involved, LINQ can almost always be
forced to do the work. But I'd agree with you that in this case, it
would not add anything useful to the implementation to use LINQ.

Pete

It does not work with List<string> because your solution is not modifying
the list object itself (as needed by the OP). it is modifying individual
objects referenced by the list.

Your solution is not actually LINQ, but it uses List<T> members that
could be thought of LINQ predecessors. As such, it is "LINQ-like". :)

A LINQ solution that would address the OP's needs would look more like this:

List<string> list = ...;

list.Aggregate(0, (i, x) =>
{
if (x == "image/pjpeg")
{
list = "image/jpeg";
}

return i + 1;
});

As you can see, it is so wordy that it is hardly any better than an
explicit loop. But the real fatal flaw is that because Aggregate() is
using the IEnumerable<string> from the list, once you try to modify an
element of the list, the attempt to retrieve the next element fails with
an exception.

Sticking with the List<T> members, as in your example, you still wind up
with something like this:

List<string> list = ...;
int i = 0;

list.ForEach(x =>
{
if (x == "image/pjpeg")
{
list = "image/jpeg";
}

i++;
});

This avoids the exception, because the ForEach() method iterates through
the list elements explicitly and does not care if you modify the
collection while it is doing that.

But, the syntax really is not any better than an explicit loop, even so.

Pete

Use IndexOf to get the position of the item:

int index = list.IndexOf("image/pjpeg");
if (index != -1) {
list[index] = "image/jpeg";
}

To find multiple items:

int index = list.IndexOf("image/pjpeg");
while (index != -1) {
list[index] = "image/jpeg";
index = list.IndexOf("image/pjpeg", index + 1);
}

You can also use LINQ mehtods:

list = list.Select(s => s == "image/pjpeg" ? "image/jpeg" : s).ToList();

However, this will create a completely new list with the strings
replaced, so it is less efficient.
On Wednesday, February 17, 2010 7:43 AM vanderghast wrote:
That does not generate an error but does not change the elements in the list
either. At least, with:


List<String> tata = new List<string>();
tata.Add("image/pjpeg");
tata.Add("bozo");
tata.Add("image/pjpeg");
tata.Add("bozo");
tata.ConvertAll<string>(s => s == "image/pjpeg" ? "image/jpeg" :
s);

System.Diagnostics.Debug.Assert(tata[0] == "image/jpeg",
"convert fail");



the assertion fails.



Vanderghast, Access MVP
 
G

Guss Davey

Dim SurveyOptionList As New List(Of SurveyOptionInfo)
SurveyOptionList = SurveyOptionController.GetSurveyOptions(objSurvey.SurveyId)
For i As Integer = 0 To SurveyOptionList.Count - 1
If SurveyOptionList.Item(i).OptionName.IndexOf("]") > 0 Then
SurveyOptionList.Item(i).OptionName = ReplaceImageTokens(SurveyOptionList.Item(i).OptionName)
End If
Next

---------------

Private Function ReplaceImageTokens(ByVal strInput As String) As String
Dim strOut As String = strInput
Dim path As String = ControlPath.ToString & "Images/"
strOut = strOut.Replace("[APPROVED]", "<img align=""middle"" src=""" & path & "approved.png"">")
strOut = strOut.Replace("[CHECKMARK]", "<img align=""middle"" src=""" & path & "checkmark.png"">")
Return strOut
End Function
Hello,

I have a List<String> and I need to find if it contains "image/pjpeg".
If yes then replace it by "image/jpeg".

What is the best way to do this? I can use Contains but how to replace
that particular item?

Thanks,
Miguel
On Tuesday, February 16, 2010 1:21 PM Konrad Neitzel wrote:
Hi Shapper!




I would use something like:
place = MyList.IndexOf(ItemToSearchFor);
if (place >= 0)
{
MyList.RemoveAt(place);
MyList.Insert(place, newItemToInsert);
}

Maybe someone else finds some nice code with LINQ or so - But at least
this is a straight forward code that should work (not tested!).

Konrad
Note that a) the above only handles a single instance of the string in
the list (may or may not be fine), and b) the above involved three O(n)
operations, when one O(n) and one O(1) operation would suffice:

for (int i = 0; i < MyList.Count; i++)
{
if (MyList == "image/pjpeg")
{
MyList = "image/jpeg";

// break; here if only want to find one instance
}
}


If a loop over a collection is involved, LINQ can almost always be
forced to do the work. But I'd agree with you that in this case, it
would not add anything useful to the implementation to use LINQ.

Pete

It does not work with List<string> because your solution is not modifying
the list object itself (as needed by the OP). it is modifying individual
objects referenced by the list.

Your solution is not actually LINQ, but it uses List<T> members that
could be thought of LINQ predecessors. As such, it is "LINQ-like". :)

A LINQ solution that would address the OP's needs would look more like this:

List<string> list = ...;

list.Aggregate(0, (i, x) =>
{
if (x == "image/pjpeg")
{
list = "image/jpeg";
}

return i + 1;
});

As you can see, it is so wordy that it is hardly any better than an
explicit loop. But the real fatal flaw is that because Aggregate() is
using the IEnumerable<string> from the list, once you try to modify an
element of the list, the attempt to retrieve the next element fails with
an exception.

Sticking with the List<T> members, as in your example, you still wind up
with something like this:

List<string> list = ...;
int i = 0;

list.ForEach(x =>
{
if (x == "image/pjpeg")
{
list = "image/jpeg";
}

i++;
});

This avoids the exception, because the ForEach() method iterates through
the list elements explicitly and does not care if you modify the
collection while it is doing that.

But, the syntax really is not any better than an explicit loop, even so.

Pete

Use IndexOf to get the position of the item:

int index = list.IndexOf("image/pjpeg");
if (index != -1) {
list[index] = "image/jpeg";
}

To find multiple items:

int index = list.IndexOf("image/pjpeg");
while (index != -1) {
list[index] = "image/jpeg";
index = list.IndexOf("image/pjpeg", index + 1);
}

You can also use LINQ mehtods:

list = list.Select(s => s == "image/pjpeg" ? "image/jpeg" : s).ToList();

However, this will create a completely new list with the strings
replaced, so it is less efficient.
On Wednesday, February 17, 2010 7:43 AM vanderghast wrote:
That does not generate an error but does not change the elements in the list
either. At least, with:


List<String> tata = new List<string>();
tata.Add("image/pjpeg");
tata.Add("bozo");
tata.Add("image/pjpeg");
tata.Add("bozo");
tata.ConvertAll<string>(s => s == "image/pjpeg" ? "image/jpeg" :
s);

System.Diagnostics.Debug.Assert(tata[0] == "image/jpeg",
"convert fail");



the assertion fails.



Vanderghast, Access MVP
On Thursday, May 12, 2011 7:37 AM Guss Davey wrote:
Dim SurveyOptionList As New List(Of SurveyOptionInfo)

SurveyOptionList = SurveyOptionController.GetSurveyOptions(objSurvey.SurveyId)

For i As Integer = 0 To SurveyOptionList.Count - 1

If SurveyOptionList.Item(i).OptionName.IndexOf("]") > 0 Then

SurveyOptionList.Item(i).OptionName = ReplaceImageTokens(SurveyOptionList.Item(i).OptionName)

End If

Next



---------------



Private Function ReplaceImageTokens(ByVal strInput As String) As String

Dim strOut As String = strInput

Dim path As String = ControlPath.ToString & "Images/"

strOut = strOut.Replace("[APPROVED]", "<img align=""middle"" src=""" & path & "approved.png"">")

strOut = strOut.Replace("[CHECKMARK]", "<img align=""middle"" src=""" & path & "checkmark.png"">")

Return strOut

End Function
 
G

Guss Davey

Dim SurveyOptionList As New List(Of SurveyOptionInfo)
SurveyOptionList = SurveyOptionController.GetSurveyOptions(objSurvey.SurveyId)
For i As Integer = 0 To SurveyOptionList.Count - 1
If SurveyOptionList.Item(i).OptionName.IndexOf("]") > 0 Then
SurveyOptionList.Item(i).OptionName = ReplaceImageTokens(SurveyOptionList.Item(i).OptionName)
End If
Next

---------------

Private Function ReplaceImageTokens(ByVal strInput As String) As String
Dim strOut As String = strInput
Dim path As String = ControlPath.ToString & "Images/"
strOut = strOut.Replace("[APPROVED]", "<img align=""middle"" src=""" & path & "approved.png"">")
strOut = strOut.Replace("[CHECKMARK]", "<img align=""middle"" src=""" & path & "checkmark.png"">")
Return strOut
End Function
Hello,

I have a List<String> and I need to find if it contains "image/pjpeg".
If yes then replace it by "image/jpeg".

What is the best way to do this? I can use Contains but how to replace
that particular item?

Thanks,
Miguel
On Tuesday, February 16, 2010 1:21 PM Konrad Neitzel wrote:
Hi Shapper!




I would use something like:
place = MyList.IndexOf(ItemToSearchFor);
if (place >= 0)
{
MyList.RemoveAt(place);
MyList.Insert(place, newItemToInsert);
}

Maybe someone else finds some nice code with LINQ or so - But at least
this is a straight forward code that should work (not tested!).

Konrad
Note that a) the above only handles a single instance of the string in
the list (may or may not be fine), and b) the above involved three O(n)
operations, when one O(n) and one O(1) operation would suffice:

for (int i = 0; i < MyList.Count; i++)
{
if (MyList == "image/pjpeg")
{
MyList = "image/jpeg";

// break; here if only want to find one instance
}
}


If a loop over a collection is involved, LINQ can almost always be
forced to do the work. But I'd agree with you that in this case, it
would not add anything useful to the implementation to use LINQ.

Pete

It does not work with List<string> because your solution is not modifying
the list object itself (as needed by the OP). it is modifying individual
objects referenced by the list.

Your solution is not actually LINQ, but it uses List<T> members that
could be thought of LINQ predecessors. As such, it is "LINQ-like". :)

A LINQ solution that would address the OP's needs would look more like this:

List<string> list = ...;

list.Aggregate(0, (i, x) =>
{
if (x == "image/pjpeg")
{
list = "image/jpeg";
}

return i + 1;
});

As you can see, it is so wordy that it is hardly any better than an
explicit loop. But the real fatal flaw is that because Aggregate() is
using the IEnumerable<string> from the list, once you try to modify an
element of the list, the attempt to retrieve the next element fails with
an exception.

Sticking with the List<T> members, as in your example, you still wind up
with something like this:

List<string> list = ...;
int i = 0;

list.ForEach(x =>
{
if (x == "image/pjpeg")
{
list = "image/jpeg";
}

i++;
});

This avoids the exception, because the ForEach() method iterates through
the list elements explicitly and does not care if you modify the
collection while it is doing that.

But, the syntax really is not any better than an explicit loop, even so.

Pete

Use IndexOf to get the position of the item:

int index = list.IndexOf("image/pjpeg");
if (index != -1) {
list[index] = "image/jpeg";
}

To find multiple items:

int index = list.IndexOf("image/pjpeg");
while (index != -1) {
list[index] = "image/jpeg";
index = list.IndexOf("image/pjpeg", index + 1);
}

You can also use LINQ mehtods:

list = list.Select(s => s == "image/pjpeg" ? "image/jpeg" : s).ToList();

However, this will create a completely new list with the strings
replaced, so it is less efficient.
On Wednesday, February 17, 2010 7:43 AM vanderghast wrote:
That does not generate an error but does not change the elements in the list
either. At least, with:


List<String> tata = new List<string>();
tata.Add("image/pjpeg");
tata.Add("bozo");
tata.Add("image/pjpeg");
tata.Add("bozo");
tata.ConvertAll<string>(s => s == "image/pjpeg" ? "image/jpeg" :
s);

System.Diagnostics.Debug.Assert(tata[0] == "image/jpeg",
"convert fail");



the assertion fails.



Vanderghast, Access MVP
On Thursday, May 12, 2011 7:37 AM Guss Davey wrote:
Dim SurveyOptionList As New List(Of SurveyOptionInfo)

SurveyOptionList = SurveyOptionController.GetSurveyOptions(objSurvey.SurveyId)

For i As Integer = 0 To SurveyOptionList.Count - 1

If SurveyOptionList.Item(i).OptionName.IndexOf("]") > 0 Then

SurveyOptionList.Item(i).OptionName = ReplaceImageTokens(SurveyOptionList.Item(i).OptionName)

End If

Next



---------------



Private Function ReplaceImageTokens(ByVal strInput As String) As String

Dim strOut As String = strInput

Dim path As String = ControlPath.ToString & "Images/"

strOut = strOut.Replace("[APPROVED]", "<img align=""middle"" src=""" & path & "approved.png"">")

strOut = strOut.Replace("[CHECKMARK]", "<img align=""middle"" src=""" & path & "checkmark.png"">")

Return strOut

End Function
On Thursday, May 12, 2011 7:38 AM Guss Davey wrote:
Dim SurveyOptionList As New List(Of SurveyOptionInfo)

SurveyOptionList = SurveyOptionController.GetSurveyOptions(objSurvey.SurveyId)

For i As Integer = 0 To SurveyOptionList.Count - 1

If SurveyOptionList.Item(i).OptionName.IndexOf("]") > 0 Then

SurveyOptionList.Item(i).OptionName = ReplaceImageTokens(SurveyOptionList.Item(i).OptionName)

End If

Next



---------------



Private Function ReplaceImageTokens(ByVal strInput As String) As String

Dim strOut As String = strInput

Dim path As String = ControlPath.ToString & "Images/"

strOut = strOut.Replace("[APPROVED]", "<img align=""middle"" src=""" & path & "approved.png"">")

strOut = strOut.Replace("[CHECKMARK]", "<img align=""middle"" src=""" & path & "checkmark.png"">")

Return strOut

End Function
 

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

Similar Threads


Top