C / C # / C ++에서 역방향 루프를 수행하는 가장 좋은 방법은 무엇입니까?
배열을 통해 뒤로 이동해야하므로 다음과 같은 코드가 있습니다.
for (int i = myArray.Length - 1; i >= 0; i--)
{
// Do something
myArray[i] = 42;
}
이 작업을 수행하는 더 좋은 방법이 있습니까?
업데이트 : 나는 C #에 다음과 같은 내장 메커니즘이 있기를 바라고 있습니다.
foreachbackwards (int i in myArray)
{
// so easy
}
업데이트 2 :이 있습니다 더 나은 방법이. 룬은 다음과 함께 상을받습니다 :
for (int i = myArray.Length; i-- > 0; )
{
//do something
}
//or
for (int i = myArray.Length; i --> 0; )
{
// do something
}
일반 C에서 더 좋아 보입니다 (Twotymz 덕분에).
for (int i = lengthOfArray; i--; )
{
//do something
}
분명히 약간 모호하지만 인쇄 상으로 가장 즐거운 방법은 다음과 같습니다.
for (int i = myArray.Length; i --> 0; )
{
//do something
}
C ++에서는 기본적으로 반복자 또는 인덱스를 사용하여 반복 할 수 있습니다. 일반 배열 std::vector
을 사용 하는지 또는 을 사용 하는지에 따라 다른 기술을 사용합니다.
std :: vector 사용
반복기 사용
C ++를 사용하면 다음을 사용할 수 있습니다. std::reverse_iterator:
for(std::vector<T>::reverse_iterator it = v.rbegin(); it != v.rend(); ++it) {
/* std::cout << *it; ... */
}
인덱스 사용
에서 반환 된 부호없는 정수 유형 std::vector<T>::size
이 항상 은 아닙니다std::size_t
. 더 크거나 작을 수 있습니다. 이것은 루프가 작동하는 데 중요합니다.
for(std::vector<int>::size_type i = someVector.size() - 1;
i != (std::vector<int>::size_type) -1; i--) {
/* std::cout << someVector[i]; ... */
}
부호없는 정수 유형 값은 모듈로 비트 수를 통해 정의되기 때문에 작동합니다. 따라서을 설정 -N
하면(2 ^ BIT_SIZE) -N
배열 사용
반복기 사용
우리는 std::reverse_iterator
반복을 위해 사용 하고 있습니다.
for(std::reverse_iterator<element_type*> it(a + sizeof a / sizeof *a), itb(a);
it != itb;
++it) {
/* std::cout << *it; .... */
}
인덱스 사용
항상 정의에 따라 반환 std::size_t
되기 때문에 위와 반대로 여기서 안전하게 사용할 수 있습니다 .sizeof
std::size_t
for(std::size_t i = (sizeof a / sizeof *a) - 1; i != (std::size_t) -1; i--) {
/* std::cout << a[i]; ... */
}
포인터에 sizeof를 적용하여 함정 피하기
실제로 배열의 크기를 결정하는 위의 방법은 짜증납니다. a가 실제로 배열 대신 포인터 인 경우 (매우 자주 발생하며 초보자가 혼동 할 것임) 조용히 실패합니다. 더 좋은 방법은 다음을 사용하는 것입니다. 포인터가 주어지면 컴파일 타임에 실패합니다.
template<typename T, std::size_t N> char (& array_size(T(&)[N]) )[N];
먼저 전달 된 배열의 크기를 가져온 다음 동일한 크기의 char 유형 배열에 대한 참조를 반환하도록 선언하여 작동합니다. char
이 정의된다 sizeof
반환 된 배열이있을 것이다 그래서 1 :의 sizeof
우리는 컴파일 타임 평가 제로 런타임 오버 헤드, 무엇을 찾고있다 N * 1 :의를.
하는 대신
(sizeof a / sizeof *a)
이제 코드를 변경하십시오.
(sizeof array_size(a))
C # 에서는 Visual Studio 2005 이상을 사용하여 'forr'를 입력하고 [TAB] [TAB] 키를 누릅니다 . for
컬렉션을 거꾸로 진행 하는 루프로 확장됩니다 .
(적어도 저에게는) 오해하기가 너무 쉽기 때문에이 스 니펫을 넣는 것이 좋은 생각이라고 생각했습니다.
즉, 나는 Array.Reverse()
/를 좋아 Enumerable.Reverse()
하고 앞으로 더 잘 반복 합니다.
나는 항상 ' 인쇄 상으로 유쾌한 '코드보다 명확한 코드를 선호 합니다. 따라서 항상 다음을 사용합니다.
for (int i = myArray.Length - 1; i >= 0; i--)
{
// Do something ...
}
거꾸로 반복하는 표준 방법으로 간주 할 수 있습니다.
내 2 센트 만 ...
에서 C #을 사용하여 Linq에를 :
foreach(var item in myArray.Reverse())
{
// do something
}
길이가 부호있는 정수 유형 인 배열에 대해 확실히 가장 좋은 방법입니다. 길이가 부호없는 정수 유형 (예 : std::vector
C ++) 인 배열의 경우 종료 조건을 약간 수정해야합니다.
for(size_t i = myArray.size() - 1; i != (size_t)-1; i--)
// blah
방금 말한 경우 i >= 0
부호없는 정수의 경우 항상 참이므로 루프는 무한 루프가됩니다.
나에게 좋아 보인다. 인덱서가 서명되지 않은 경우 (uint 등)이를 고려해야 할 수 있습니다. lazy라고 부르지 만 (서명되지 않은) 경우에는 카운터 변수를 사용할 수 있습니다.
uint pos = arr.Length;
for(uint i = 0; i < arr.Length ; i++)
{
arr[--pos] = 42;
}
(실제로 여기에서도 arr.Length = uint.MaxValue ... 어딘가에! = 어딘가에있는 경우와 같은 경우에주의해야합니다 ... 물론 가능성이 매우 낮은 경우입니다!)
CI에서는 다음과 같이합니다.
int i = myArray.Length;
while (i--) {
myArray[i] = 42;
}
MusiGenesis에서 추가 한 C # 예제 :
{int i = myArray.Length; while (i-- > 0)
{
myArray[i] = 42;
}}
C ++에서이를 수행하는 가장 좋은 방법은 순회되는 시퀀스를 느리게 변환하는 반복기 (또는 더 나은 범위) 어댑터를 사용하는 것입니다.
원래,
vector<value_type> range;
foreach(value_type v, range | reversed)
cout << v;
범위 "범위"(여기서는 비어 있지만 요소를 직접 추가 할 수 있다고 확신합니다)를 역순으로 표시합니다. 물론 단순히 범위를 반복하는 것은별로 소용이 없지만 새로운 범위를 알고리즘과 물건에 전달하는 것은 꽤 멋지다.
이 메커니즘은 훨씬 더 강력한 용도로도 사용할 수 있습니다.
range | transformed(f) | filtered(p) | reversed
함수 "f"가 모든 요소에 적용되고 "p"가 참이 아닌 요소는 제거되고 최종적으로 결과 범위가 반전되는 "범위"범위를 느리게 계산합니다.
파이프 구문은 중위를 감안할 때 가장 읽기 쉬운 IMO입니다. Boost.Range 라이브러리 업데이트 보류 검토가이를 구현하지만 직접 수행하는 것도 매우 간단합니다. 함수 f와 술어 p를 인라인으로 생성하는 람다 DSEL을 사용하면 훨씬 더 멋집니다.
// this is how I always do it
for (i = n; --i >= 0;){
...
}
while 루프를 선호합니다. i
for 루프의 조건에서 감소하는 것보다 더 분명합니다.
int i = arrayLength;
while(i)
{
i--;
//do something with array[i]
}
원래 질문에서 코드를 사용하고 싶지만 실제로 foreach를 사용하고 C #에서 정수 인덱스를 사용하려면 다음을 수행하십시오.
foreach (int i in Enumerable.Range(0, myArray.Length).Reverse())
{
myArray[i] = 42;
}
선에 명확성이나 유지 관리가 포함되어 있다면 대안이 더 좋은 이유를 알 수 없습니다.
여기에서 내 질문에 답해 보려고하지만 이것도별로 마음에 들지 않습니다.
for (int i = 0; i < myArray.Length; i++)
{
int iBackwards = myArray.Length - 1 - i; // ugh
myArray[iBackwards] = 666;
}
참고 :이 게시물은 훨씬 더 자세하게 작성되어 주제에서 벗어났습니다. 사과드립니다.
내 동료들은 그것을 읽고 그것이 '어딘가'에 가치 있다고 믿습니다. 이 실은 장소가 아닙니다. 이것이 어디로 가야하는지에 대한 귀하의 의견에 감사드립니다 (저는 사이트를 처음 사용합니다).
어쨌든 이것은 정의 된 의미 체계를 사용하는 모든 컬렉션 유형에서 작동한다는 점에서 놀라운 .NET 3.5의 C # 버전입니다. 이것은 실제 세계에서 일어나는 것처럼 보이지 않지만 (조기 최적화) 대부분의 일반적인 개발 시나리오에서 성능이나 CPU주기 최소화가 아닌 기본 측정 (재사용!)입니다.
*** 모든 컬렉션 유형에 대해 작동하고 유형의 단일 값을 예상하는 작업 대리자를 취하는 확장 메서드, 모두 역순으로 각 항목에 대해 실행 **
요구 사항 3.5 :
public static void PerformOverReversed<T>(this IEnumerable<T> sequenceToReverse, Action<T> doForEachReversed)
{
foreach (var contextItem in sequenceToReverse.Reverse())
doForEachReversed(contextItem);
}
이전 .NET 버전 또는 Linq 내부를 더 잘 이해하고 싶습니까? 계속 읽어봐 .. 아니면 ..
가정 : .NET 유형 시스템에서 Array 유형은 IEnumerable 인터페이스에서 상속됩니다 (일반 IEnumerable 전용 IEnumerable이 아님).
이것은 처음부터 끝까지 반복하는 데 필요한 전부이지만 반대 방향으로 이동하고 싶습니다. IEnumerable이 '객체'유형의 배열에서 작동하므로 모든 유형이 유효합니다.
중요 측정 : '더 나은'시퀀스를 역순으로 처리 할 수 있다면 정수에서만 처리 할 수 있다고 가정합니다.
.NET CLR 2.0-3.0 용 솔루션 A :
설명 : 포함 된 각 인스턴스가 동일한 유형임을 요구하는 모든 IEnumerable 구현 인스턴스를 허용합니다. 따라서 배열을 받으면 전체 배열에 X 유형의 인스턴스가 포함됩니다. 다른 인스턴스가! = X 유형이면 예외가 발생합니다.
싱글 톤 서비스 :
공용 클래스 ReverserService {개인 ReverserService () {}
/// <summary>
/// Most importantly uses yield command for efficiency
/// </summary>
/// <param name="enumerableInstance"></param>
/// <returns></returns>
public static IEnumerable ToReveresed(IEnumerable enumerableInstance)
{
if (enumerableInstance == null)
{
throw new ArgumentNullException("enumerableInstance");
}
// First we need to move forwarad and create a temp
// copy of a type that allows us to move backwards
// We can use ArrayList for this as the concrete
// type
IList reversedEnumerable = new ArrayList();
IEnumerator tempEnumerator = enumerableInstance.GetEnumerator();
while (tempEnumerator.MoveNext())
{
reversedEnumerable.Add(tempEnumerator.Current);
}
// Now we do the standard reverse over this using yield to return
// the result
// NOTE: This is an immutable result by design. That is
// a design goal for this simple question as well as most other set related
// requirements, which is why Linq results are immutable for example
// In fact this is foundational code to understand Linq
for (var i = reversedEnumerable.Count - 1; i >= 0; i--)
{
yield return reversedEnumerable[i];
}
}
}
public static class ExtensionMethods
{
public static IEnumerable ToReveresed(this IEnumerable enumerableInstance)
{
return ReverserService.ToReveresed(enumerableInstance);
}
}
[TestFixture] public class Testing123 {
/// <summary>
/// .NET 1.1 CLR
/// </summary>
[Test]
public void Tester_fornet_1_dot_1()
{
const int initialSize = 1000;
// Create the baseline data
int[] myArray = new int[initialSize];
for (var i = 0; i < initialSize; i++)
{
myArray[i] = i + 1;
}
IEnumerable _revered = ReverserService.ToReveresed(myArray);
Assert.IsTrue(TestAndGetResult(_revered).Equals(1000));
}
[Test]
public void tester_why_this_is_good()
{
ArrayList names = new ArrayList();
names.Add("Jim");
names.Add("Bob");
names.Add("Eric");
names.Add("Sam");
IEnumerable _revered = ReverserService.ToReveresed(names);
Assert.IsTrue(TestAndGetResult(_revered).Equals("Sam"));
}
[Test]
public void tester_extension_method()
{
// Extension Methods No Linq (Linq does this for you as I will show)
var enumerableOfInt = Enumerable.Range(1, 1000);
// Use Extension Method - which simply wraps older clr code
IEnumerable _revered = enumerableOfInt.ToReveresed();
Assert.IsTrue(TestAndGetResult(_revered).Equals(1000));
}
[Test]
public void tester_linq_3_dot_5_clr()
{
// Extension Methods No Linq (Linq does this for you as I will show)
IEnumerable enumerableOfInt = Enumerable.Range(1, 1000);
// Reverse is Linq (which is are extension methods off IEnumerable<T>
// Note you must case IEnumerable (non generic) using OfType or Cast
IEnumerable _revered = enumerableOfInt.Cast<int>().Reverse();
Assert.IsTrue(TestAndGetResult(_revered).Equals(1000));
}
[Test]
public void tester_final_and_recommended_colution()
{
var enumerableOfInt = Enumerable.Range(1, 1000);
enumerableOfInt.PerformOverReversed(i => Debug.WriteLine(i));
}
private static object TestAndGetResult(IEnumerable enumerableIn)
{
// IEnumerable x = ReverserService.ToReveresed(names);
Assert.IsTrue(enumerableIn != null);
IEnumerator _test = enumerableIn.GetEnumerator();
// Move to first
Assert.IsTrue(_test.MoveNext());
return _test.Current;
}
}
참고URL : https://stackoverflow.com/questions/275994/whats-the-best-way-to-do-a-backwards-loop-in-c-c-c
'IT박스' 카테고리의 다른 글
파이썬-파이썬에서 URL의 유효성을 검사하는 방법은 무엇입니까? (0) | 2020.09.02 |
---|---|
Swift 3의 NotificationCenter 문제 (0) | 2020.09.02 |
행을 계산하는 Android의 SQLite 쿼리 (0) | 2020.09.02 |
Storyboard에서 간단한 둥근 버튼을 만드는 방법은 무엇입니까? (0) | 2020.09.02 |
Mountain Lion에 소켓 파일“/var/pgsql_socket/.s.PGSQL.5432”누락 (OS X 서버) (0) | 2020.09.02 |