2012-05-19 3 views
0

중첩 for/foreach 루프를 사용하여 목록의 항목을 변경해야합니다. 문제는 점 표기법 사용 여부에 관계없이 LINQ를 사용하여 작동하지 못하는 것입니다. 전통적인 방법이 근무하고 같이 간다 : LINQ를 사용하여목록 항목을 변경하기 위해 중첩 된 foreach

foreach (MapObjectLayer mapObjectLayer in map.Objects) 
{ 
    foreach (MapObject mapObject in mapObjectLayer.MapObjects) 
    { 
     for (int i = 0; i < mapObject.Points.Count; i++) 
     { 
      mapObject.Points[i] = new Vector2(
       mapObject.Points[i].X * map.Scale, 
       mapObject.Points[i].Y * map.Scale); 
     } 
    } 
} 

이 실패 :

var test = (from mol in map.Objects 
      from mo in mol.MapObjects 
      from p in mo.Points 
      select p).ToList(); 

for (int i = 0; i < test.Count(); i++) 
{ 
    test[i] = new Vector2(
     test[i].X * map.Scale, 
     test[i].Y * map.Scale); 
} 

이 실패 :

map.Objects.ForEach(l => l.MapObjects.ForEach(t => t.Points.ForEach(p => p = p * map.Scale))); 

나는 점 표기법 변형을 얻을 수 있다면 작업 나는 매우 행복 할 것이지만, 그것이 실패한 이유에 대한 단서가 없습니다. 디버거를 사용하면 벡터가 두 개의 LINQ 변형을 사용하여 곱 해지지 않았다는 점을 Points 목록에서 확인하는 것이 분명합니다.

업데이트 : 여기 내가 찾은 두 개 더 한 라이너 (일하는 사람)입니다 : Vector2는 구조체

업데이트입니다

map.Objects.SelectMany(m => m.MapObjects).ToList().ForEach(o => o.Points = o.Points.Select(p => p * 2).ToList()); 
map.Objects.ForEach(l => l.MapObjects.ForEach(t => t.Points = t.Points.Select(p => p * 2).ToList())); 
+1

왜 LINQ로 설정해야합니까? – undefined

+3

왜 LINQ를 사용하고 싶습니까? LINQ는 * 업데이트 *가 아닌 * 쿼리 * 용입니다. –

+0

LINQ가 실제로 더 느릴 수도 있다고 생각합니다. "멋진 한 줄자"를 찾고 있습니까? –

답변

2

정규 foreach이 가장 좋은 방법입니다. LINQ는 쿼리 용으로 설계되었습니다. 한 줄로 처리 할 수 ​​있지만 우아하거나 읽을 수는 없습니다. Vector2는 값 형식이므로 버전이 작동하지 않았다

map.Objects.ForEach(l => l.MapObjects.ForEach(t => Enumerable.Range(0, t.Points.Count).ToList().ForEach(i => t.Points[i] *= map.Scale))); 

이유는 방법은 다음과 같습니다이다. 쿼리에서는 값이 복사되므로 p => p = ...을 지정하면 변수 복사본에 할당됩니다.

원본 코드를 사용하십시오. LINQ는 루프를 대체하지 않습니다.

+0

이것은 내 질문에 매우 잘 답변하고 한 줄짜리 감사합니다. 내가 혼란에 빠지면, 아마 foreach 루프를 사용합니다. 감사합니다. –

+0

질문에 답변이 있으면 대답으로 표시하십시오. –

+0

완료되었지만 Enumerable.Range (0, t.Points.Count)와 .ForEach 함수 사이에 .ToList()가 없습니다 (그렇지 않으면 컴파일되지 않습니다). –

1

Linq를 사용하여 항목을 수집 할 수도 있습니다. 실제로 Resharper는 중첩 된 foreach에서 linq으로 리팩터링을 제공하지만 수집 한 항목과 업데이트하는 항목은주의해야합니다.

초기 linq 쿼리 구문 예제는 Points의 복사본을 새 List로 수집 한 다음이 새 목록의 각 요소를 Vector2의 새 인스턴스로 바꿉니다. Vector2가 참조 유형 일지라도 원래 목록보다는 새 목록 만 변경됩니다. 객체 - 하부 구조.

그것은 당신이 원하는 방식으로 일하는 것이 그것을 경우

당신이 참조가 아닌 값 유형과
  • 당신이 대신 -의 - Vector2 항목의 속성을 지정할 것 작동

    • :

      test [i] .X * = map.Scale