views:

123

answers:

5

I have a class called Questions. This Questions has properties QuestionID and QuestionAnswer. While iterating through this List of Question in foreach, I have to find .QuestionID = 12. If I find .QuestionID = 12 then I have to immediately assign a value to .QuestionAnswer = "SomeText" of .QuestionID = 14.

I don't want iterate again inside .QuestionId = 12' to find.QuestionID = 14` again.

Is there any way I can go directly to .QuestionID = 14 using LINQ?.

For example:

For Each mQuestion As Question In _mQuestions
    If mQuestion.QuestionId = 12 Then
         'Find mQuestion.QuestionID= 14 and insert Somtext to 
          'mQuestion.QuestionAnswer="SomeText"
    End IF
Next
+3  A: 

I think you're looking for something like this. If I have a moment, I'll translate it to VB, but I think you can follow.

if (_mQuestions.Any(q => q.QuestionID == 12)) 
{
   Question question14 = _mQuestions.FirstOrDefault(q => q.QuestionID == 14);
   if (question14 != null)
       question14.QuestionAnswer = "Some Text";
}
Anthony Pegram
Please don't encourage people by translating perfectly good code to VB. :)
Dave Markle
A: 

Unfortunately, your data structure (List) requires that you search again to find Question-14 once Question-12 is found. If your Question list is sorted by ID, then some improvements can be made, but in general, there is no way to directly access an element of a List or Array by only knowing the values of the element's property.

The data structure that is applicable to your problem is Dictionary as it allows indexing of objects via some value, as well as efficient direct-access to those objects without the need to iterate through the entire collection.

You can covert your list to a dictionary using Linq by calling the ToDictionary() extension method:

IDictionary<Question> questions = _mQuestions.ToDictionary(q => q.id);

This uses the ID of the Question object as the key, and the object as the value. Then in your code, you can do the following:

if (questions.ContainsKey(12) && questions.ContainsKey(14))
{
    questions[14].QuestionAnswer = "Some Text";
}

Note that ContainsKey and the indexer (operator[]) both execute in constant time.

Steve Guidi
A: 

Mind you, my take on it is a bit more wordy than the other samples, but I managed to do it with nothing but LINQ. (Watch out for the C-style comments below!)

Private Shared Sub Main(args As String())
    Dim questions As List(Of Question) = GetQuestions()
    Dim question As Question = ( _
        Where q.ID = 14 AndAlso _
              questions.Exists(Function(p) p.ID = 12)).FirstOrDefault()
    If question IsNot Nothing Then
        question.Answer = "Some Text"
    End If
End Sub



 // Build the collection of questions! We keep this simple.
Private Shared Function GetQuestions() As List(Of Question)
    Dim questions As New List(Of Question)()
    questions.Add(New Question(12, "foo"))
    questions.Add(New Question(14, "bar"))
    Return questions
End Function

// You've already got this class. This one is just my version.
Public Class Question
    Public Sub New(id As Integer, answer As String)
        Me.ID = id
        Me.Answer = answer
    End Sub
    Public Property ID() As Integer
        Get
            Return m_ID
        End Get
        Set
            m_ID = Value
        End Set
    End Property
    Private m_ID As Integer
    Public Property Answer() As String
        Get
            Return m_Answer
        End Get
        Set
            m_Answer = Value
        End Set
    End Property
    Private m_Answer As String
End Class
Mike Hofer
A: 

Using LINQ:

var listOfQ = new List<Question>();

// populate the list of Question somehow...

var q14 = listOfQ.FirstOrDefault(q => q.QuestionID == 14);
if (listOfQ.Any(q => q.QuestionID == 12) && q14 != null)
{
    q14.QuestionAnswer = "SomeText";
}
code4life
A: 

use this:

myList.Select(q=>
{
if (q.id == 14) 
    q.Value = "text";
return q.id == 14;
});

also u can use extension method (but it uses foreach):

myList.Select(q=>q.id == 14).Set("text");

then u can do this:

public static void Set(this MyListType input, string text)
{
  foreach(var item in input)
  item.Value = "text";
}

if is just one item in situation do this:

myList.FirstOrDefault(q=>q.id == 14).SetOne("text")

your method is like this:

public static void SetOne(this QuestionType input, string text)
{
  input.Value =text;
}
SaeedAlg