Cách rõ ràng để bỏ qua phần tử đầu tiên trong một chỉ mục dựa trên vòng lặp


9

Tôi có một vòng lặp for trong đó tôi phải bỏ qua phần tử đầu tiên trong một mảng dựa trên zero.

Những điều này cho thấy ý định của tôi rõ ràng hơn?

for($i=1 ; $i < count(array) ; $i++){
    array[$i];
}

hoặc là

for($i=0+1 ; $i < count(array) ; $i++){
    array[$i];
}

28
Không phải, $i=2-1là cách vượt trội. : /
yannis

7
Có lẽ tôi nên chọn tùy chọn đầu tiên và thêm một nhận xét để giải thích tại sao phần tử đầu tiên phải được bỏ qua.
Vincent Savard

3
Clearness là những gì tôi đang hướng tới, tôi đã chỉnh sửa câu hỏi. Có rõ ràng hơn không?
Tomas Zubiri

10
Không sử dụng PHP là cách vượt trội.
con mèo

3
PHP có một cấu trúc foreach không? Bạn có thể làm foreach ($i in range(1, count))(bất cứ điều gì trông giống như trong PHP). Hoặc một cái gì đó giống như foreach ($item in array.skip(1))đó là những gì một người C # sẽ làm.
usr

Câu trả lời:


23

Tôi ghét cả hai.

Ai nói bạn có thể sử dụng số ma thuật? Nếu bạn sẽ bắt đầu ở độ lệch 1 thì làm thế nào để nói với chúng tôi TẠI SAO bạn bắt đầu ở độ lệch bằng 1. Thêm một số 0 ma thuật tương đương không giải thích gì cho tôi.

Đây có phải là tải trọng bù? Đây có phải là một chuỗi pascal mà bạn đang chuyển đổi thành một chuỗi c kết thúc không? Xin vui lòng cho chúng tôi biết những gì đang xảy ra.

Xin lỗi, nhưng tôi đã lãng phí phần lớn sự nghiệp của mình để giải mã những bí ẩn vô nghĩa như thế này và sự kiên nhẫn của tôi dành cho họ đã cạn kiệt. Là một biến với một tên phong nha thực sự nhiều để hỏi?

Theo tên đàng hoàng, ý tôi là một cái tên giải thích TẠI SAO chúng ta bỏ qua phần tử đầu tiên. Không phải cái gì đơn giản chỉ nói RATNG chúng ta bỏ qua yếu tố đầu tiên. 1 nói với tôi rằng đó là của riêng mình.


19
0 và 1 không phải là số ma thuật.
dùng949300

19
@ user949300 Ồ chắc chắn họ ở đây. Chúng chỉ đơn giản là những con số đôi khi không phải là phép thuật. Chỉ vì 2 luôn là số ma thuật không có nghĩa là 1 không bao giờ là số ma thuật. Sự kỳ diệu đến từ ý nghĩa còn thiếu. Cái quái gì bắt đầu từ 1 offset có ý nghĩa gì ở đây? Thêm 0 làm gì ở đây? Ồ vâng, những con số này chắc chắn là kỳ diệu ở đây. Tôi có thể thấy bụi pixie nhỏ giọt từ chúng.
candied_orange

4
Chắc chắn, tôi sẽ bắt đầu xác định static final int LONELIEST_NUMBER = 1trong tất cả các mã Java của mình. :-) Điều đó nói rằng, tôi nghĩ rằng tôi muốn tiết lộ câu trả lời của bạn nhưng không thể trừ khi bạn chỉnh sửa nó. Quy tắc ngớ ngẩn SO?
dùng949300

6
@Eiko: Nếu không có lời giải thích tại sao vòng lặp bắt đầu ở phần tử thứ hai, thì hầu như đảm bảo rằng một số lập trình viên bảo trì sẽ thay đổi vòng lặp để bắt đầu ở phần tử đầu tiên. Đó là lý do tại sao chữ số 1 là một con số kỳ diệu trong bối cảnh này.
Bart van Ingen Schenau

2
@BartvanIngenSchenau Tôi cho rằng sẽ có một lý do có thể nhìn thấy ngay lập tức trong bối cảnh. Giống như so sánh các yếu tố với người tiền nhiệm của chúng (mà tôi nghĩ là trường hợp sử dụng thường xuyên nhất để bắt đầu từ 1 - và tôi không thấy bất kỳ tên hằng hữu ích nào ở đây). Nếu phần tử đầu tiên có ý nghĩa cực kỳ đặc biệt, thiết kế có thể bị hỏng và cần có cách khắc phục tốt hơn so với đặt tên cho chỉ mục đó. Tôi không nói rằng không bao giờ có một lý do để giới thiệu một biến ở đây. Chỉ là tôi nghĩ rằng những trường hợp đó là (hoặc có lẽ chỉ nên) rất hiếm.
Eiko

12

Câu trả lời ngắn: tùy chọn đầu tiên là tốt hơn.

Tùy chọn thứ hai chỉ thêm tiếng ồn. Rất khó có khả năng 0 + 1 giúp người đọc hiểu rằng nó có thể là 0 nhưng là 1. Nhiều khả năng anh ta sẽ bối rối trong một khoảnh khắc ngắn và mất tập trung vào những gì vòng lặp nói về. Đặc biệt là trong một ngôn ngữ mà tất cả các mảng bắt đầu từ 0.

Như đã đề cập khác, nếu bạn muốn nhấn mạnh thực tế rằng vòng lặp bắt đầu từ 1, không phải 0, chỉ cần thêm một nhận xét.


10

Đừng nói với chúng tôi rằng bạn đang bỏ qua mục đầu tiên - chúng ta có thể thấy điều đó. Điều không rõ ràng là tại sao . Vì vậy, nếu nó không rõ ràng từ ngữ cảnh, hãy cho chúng tôi biết lý do:

// array[0] is just a header
for($i=1 ; $i < count(array) ; $i++){
    array[$i];
}

Hoặc, nếu bạn không thích bình luận, đại loại như:

$lastHeaderIndex = 0;
for($i = $lastHeaderIndex + 1 ; $i < count(array) ; $i++){
    array[$i];
}

Đừng sử dụng các bình luận và mánh khóe để nhắc nhở chúng tôi cách ngôn ngữ hoạt động.


6

Ví dụ của bạn có vẻ giả tạo. Trong mã thế giới thực, thực tế các vòng lặp cần bắt đầu ở phần tử mảng thứ hai có lẽ rõ ràng nhất từ ​​các dòng mã sau. Ví dụ, nếu mã thực sự trông như thế này

for($i=1 ; $i < count(array) ; $i++){
    array[$i-1]=array[$i];
}

sẽ không có lời giải thích hoặc cấu trúc "0 + 1" cần thiết để làm rõ lý do tại sao vòng lặp bắt đầu từ 1 thay vì 0.

Tuy nhiên, nếu mã bên trong vòng lặp không giải thích lý do theo cách rõ ràng như vậy (có thể array[0]có ý nghĩa đặc biệt và phải được xử lý khác với các yếu tố còn lại), sau đó thêm nhận xét giải thích. Nhưng trước khi bạn làm điều này, hãy suy nghĩ hai lần nếu bạn có thể tránh có array[0]ý nghĩa đặc biệt này và sắp xếp lại mã xung quanh, có lẽ sẽ là sự thay thế tốt hơn.


Trong các tình huống như mã ví dụ của bạn, tôi muốn đặt tên cho các biến là "oneBasing Index" hoặc "zeroBasing Index". Mặc dù một cái gì đó cụ thể hơn cho nhiệm vụ đó sẽ tốt hơn.
user949300

5

Chưa bao giờ thấy tùy chọn # 2, nhưng tôi thích nó. Tại sao? Với tùy chọn # 1, tôi tự hỏi liệu lập trình viên có quên rằng các mảng bắt đầu từ 0. Tùy chọn # 2 làm cho rõ ràng hơn rằng họ đang cố tình bắt đầu từ 1.

Điều đó nói rằng, tốt nhất trong cả hai trường hợp để thêm một nhận xét tại sao bạn bỏ qua yếu tố.

Hoặc, nếu bạn có thể dễ dàng mô tả lý do tại sao bạn bắt đầu tại một, hãy sử dụng một hằng số. Ví dụ, nếu nhìn vào các đối số dòng lệnh, một cái gì đó như

define ('FIRST_REAL_ARGUMENT', 1);
for ($i=FIRST_REAL_ARGUMENT; ...)

Cá nhân, có lẽ tôi chỉ sử dụng một nhận xét thay thế, YMMV.


Tôi sẽ nói rằng bên ngoài môi trường nơi bạn giao dịch với người mới bắt đầu, tôi chưa bao giờ gặp phải vấn đề đồng nghiệp quên rằng mảng bắt đầu từ 0. Tôi có thể thấy điều đó xảy ra nếu công việc của bạn cũng sử dụng một ngôn ngữ như MATLAB, nhưng trong hầu hết các môi trường, tôi cho rằng lập trình viên biết họ đang làm gì. Và chết tiệt, bắt đầu một vòng lặp ở 1 là khá phổ biến. Có khá nhiều lý do để bỏ qua yếu tố đầu tiên của một cái gì đó.
Kat

@Kat Lý do đó cần phải rõ ràng cho độc giả trong tương lai. Tôi muốn giả sử rằng một lập trình viên tương lai không biết nó đang làm gì.
A1rPun

2

Tôi nghi ngờ bất cứ ai sẽ bị nhầm lẫn bởi người đầu tiên. Tất cả chúng ta phải làm điều đó. Nhiều đến mức thứ hai dễ bị nhầm lẫn hơn. "Tại sao lại có 0+ ở đó? Họ đã ghi đè toán tử + bằng cách nào đó?"

Một trình biên dịch tốt sẽ biến cái thứ hai thành cái đầu tiên, nhưng có vẻ như bạn đang sử dụng PHP, được diễn giải. Vì vậy, mỗi khi trình thông dịch đạt được vòng lặp đó, nó sẽ thực sự phải thêm 0 và 1. Không phải là vấn đề lớn, nhưng tại sao làm cho trình thông dịch thực hiện công việc?


2

Sử dụng một biến giải thích điểm bắt đầu.

Bạn cần " bỏ qua phần tử đầu tiên trong một mảng dựa trên zero ", ví dụ:

skipFirstElement = 1;

for($i=$skipFirstElement ; $i < count(array) ; $i++){
    array[$i];
}

6
Tôi thích sử dụng một biến nhưng tôi ghét tên này. Nó không giải thích TẠI SAO bạn bỏ qua phần tử đầu tiên. 1 cho tôi biết dù sao đi nữa. Điều gì tốt là một biến cần được đổi tên khi giá trị của nó thay đổi? Tôi biết OP không cho chúng tôi biết lý do tại sao để chọn một cái tên hay mà bạn sẽ phải đưa ra lý do. Không có tên tốt hơn tôi muốn có 1 trở lại.
candied_orange

@CandiedOrange Tôi đồng ý với bạn rằng tên biến sẽ có ý nghĩa hơn, nhưng vấn đề được trình bày không giải thích lý do tại sao anh ta muốn bỏ qua giá trị đầu tiên. Quan điểm của tôi là, tôi chỉ đưa ra một ví dụ, tác giả có thể chọn một cái tên phù hợp nhất với mình.
catta

Xin đừng dạy theo cách này. Điều này đủ khó hiểu. Để nhiều lập trình viên sẽ đạt được tên dễ nhất họ có thể để họ có thể quay lại viết mã khó hiểu. Nghiêm túc mà nói, tôi thà đối phó với cái 1 còn hơn thế này.
candied_orange

1
//We are skipping the first element because...    
if ($i==0)  
{    continue;      } 

Nếu một người bị ám ảnh với tất cả các vòng lặp bắt đầu từ 0, bạn có thể sử dụng câu lệnh tiếp tục. Thêm một bình luận cho lý do tại sao bạn bỏ qua vì bình thường sẽ không.


2
Vấn đề với tùy chọn này có nghĩa là chúng ta sẽ đánh giá điều này cho từng phần tử, thêm n so sánh bổ sung vào vòng lặp, trong khi chỉ cần bỏ qua phần đầu tiên thông qua một phương thức khác (thay đổi mảng, bắt đầu bằng i = 1, bất cứ điều gì ) có nghĩa là chỉ làm công việc bạn cần.
Kevin Phí

3
@KevinFee Nếu bạn không xử lý các mảng lớn, tôi sẽ nói so sánh đơn giản này sẽ không thành vấn đề. Và tôi khá thích nhân chứng if first then skipvới một bình luận nói tại sao. Vẫn không có ngữ cảnh, không có giải pháp nào là "tốt nhất"
Ivan Pintar

-2

Những gì tôi sẽ làm là loại bỏ phần tử đầu tiên trước khi lặp. Tạo một mảng mới nếu bạn cần. Giải thích trong một nhận xét tại sao bạn làm điều đó. Và sau đó chỉ cần làm một bài giảng đơn giản.

$arrayCopy = $array; // in case you don't want to touch the original array
array_shift($arrayCopy); // removing first element because of X reason.
foreach($arrayCopy => $element) { 
    // do stuff
}

Bằng cách này, ý định của bạn là hoàn toàn rõ ràng.

Để làm rõ hơn, bạn có thể bọc mã trong một phương thức với một tên thích hợp để làm cho mọi thứ rõ ràng hơn.

function doStuffToAllButTheFirst($array) { // this copies the original array, so there are no sideffects
    array_shift($array);
    foreach($array => $element) { // do stuff }  
}

Tuy nhiên tất cả điều này vẫn còn thiếu bối cảnh. Bạn muốn làm gì với các yếu tố? Bạn sẽ trở lại mảng mới? Bạn có quan tâm đến các bản gốc và mảng mới sau bạn doStuff()?

Dù sao, không có câu trả lời rõ ràng ở đây và việc quyết định làm thế nào để đọc mã phụ thuộc rất nhiều vào bối cảnh.


1
Tôi thích điều này bởi vì tôi không cần phải xử lý các chỉ mục bây giờ, đây luôn là một điểm cộng.
Tomas Zubiri

1
Nhược điểm ở đây là nếu bạn không muốn tác dụng phụ, bạn cần sao chép toàn bộ mảng.
Tomas Zubiri

1
Và điều gì xảy ra nếu lý do chúng tôi bắt đầu từ 1 là vì chúng tôi đang làm $array[$i-1] = $array[$i]hoặc một cái gì đó tương tự, theo câu trả lời của @ DocBrown?
Kevin Phí

1
Điều này có vẻ kinh khủng với tôi. Bên cạnh tất cả sự kém hiệu quả, tác dụng phụ và không có khả năng giải quyết các trường hợp sử dụng khá phổ biến cho 1(xem bình luận của Kevin Lee), nó không làm cho mã rõ ràng hơn chút nào. Người đọc phải hiểu mảng_shift, nó làm gì, hoạt động như thế nào. Có lẽ dòng mã này là một lỗi? Nó có sửa đổi mảng hoặc trả về một cái mới không? Nó chèn một phần tử hoặc loại bỏ một phần tử? Nó có thay đổi chỉ số hay không? Tôi không thấy cách sử dụng vòng lặp một lần sẽ không phải là một cải tiến lớn trong chức năng đó (và được đặt tên của nó, có thể hiểu được ngay lập tức).
Eiko

1
Các câu trả lời cho những câu hỏi này phụ thuộc rất nhiều vào bối cảnh. Và về hiệu quả, tôi sẽ tham gia một cuộc thảo luận cho bất kỳ ngày nào ... Bất kỳ sự khác biệt về hiệu suất nào cũng gần như vô hình trong hầu hết các trường hợp.
Ivan Pintar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.