2016-06-01 17 views
5

Xin chào các bạn đang cố gắng tạo một hàm trong javascript trả về một mảng từ phạm vi (bắt đầu, kết thúc) và im phải tạo một đối số tùy chọn mặc định khi nó không được xác định. Tôi có thể nhận được các chức năng để làm việc khi tôi cung cấp tất cả các đối số nhưng trả về một mảng trống khi tôi chỉ vượt qua hai đối số. Đây là câu hỏi:tạo một hàm phạm vi trong javascript

Viết một hàm có hai đối số, bắt đầu và kết thúc và trả về một mảng chứa tất cả các số từ đầu đến cuối (và bao gồm).

Tiếp theo, viết hàm tổng có một dãy số và trả về tổng các số này. Chạy chương trình trước đó và xem liệu nó có thực sự trả lại 55.

Làm nhiệm vụ thưởng, sửa đổi hàm phạm vi của bạn để lấy một đối số thứ ba tùy chọn cho biết giá trị "bước" được sử dụng để tạo mảng. Nếu không có bước nào được đưa ra, các phần tử mảng tăng lên theo số gia của một, tương ứng với hành vi cũ. Phạm vi cuộc gọi hàm (1, 10, 2) phải trả về [1, 3, 5, 7, 9]. Hãy chắc chắn rằng nó cũng làm việc với các giá trị bước âm để phạm vi (5, 2, -1) tạo ra [5, 4, 3, 2].

và đây là mã của tôi

function range(start, end, increment){ 
var array = []; 
var current = start; 
var counter; 
if (increment == undefined){ 
    counter = 1; 
} 

else { 
    counter = increment; 
} 

if (increment > 0){ 
    while(current <= end){ 
     array.push(current); 
     current += counter; 
    } 
} 

else if (increment < 0){ 
    while(current >= end){ 
     array.push(current); 
     current += counter; 

    } 
} 

return array; 
} 

ai đó có thể giải thích lý do tại sao phá vỡ nó? tôi biết một số C# và im sử dụng để có thể nhảy vào gỡ lỗi trong visual studio khi họ gặp khó khăn không giống như javascript

+1

JS cũng có rất nhiều trình gỡ lỗi. Một trong Chrome có lẽ là tốt nhất. Mở nó ra bạn sẽ có thể bước qua mã. –

+0

Thành ngữ JS chung cho * nếu không xác định, thay vào đó là * là: 'var counter = increment || 1; ' – 4castle

+0

@ 4castle bạn có thể giải thích thêm? không thực sự chắc chắn cách thức hoạt động. nó sẽ là tốt hơn để sử dụng toán tử '?'? – Nate

Trả lời

3

Trước tiên, bạn kiểm tra xem increment là undefined và thiết lập counter cho phù hợp, nhưng sau đó bạn kiểm tra if (increment > 0){ một lần nữa. Trong khi đó là undefined không có trường hợp nào của bạn phù hợp, do đó không có gì xảy ra.

Thay đổi séc của bạn như thế này:

if (counter > 0){ 
    // ... 
} 
else if (counter < 0){ 
    // ... 
} 
4

Bạn có thể đơn giản hóa mã một chút và sử dụng biến increment cho incrementing. Nhưng trước đây, tôi khuyên bạn nên kiểm tra xem giá trị có bị lỗi hay không (0, null, undefined, v.v.) và chỉ định sau đó 1 cho nó.

Chưa được triển khai: kiểm tra xem startend có phù hợp không.

function range(start, end, increment) { 
 
    var array = []; 
 
    var current = start; 
 

 
    increment = increment || 1; 
 
    if (increment > 0) { 
 
     while (current <= end) { 
 
      array.push(current); 
 
      current += increment; 
 
     } 
 
    } else { 
 
     while (current >= end) { 
 
      array.push(current); 
 
      current += increment; 
 
     } 
 
    } 
 
    return array; 
 
} 
 

 
console.log(range(1, 3, 0));  
 
console.log(range(2, 5)); 
 
console.log(range(1, 9, 1)); 
 
console.log(range(5, 2, -1));

+1

Điều này là tốt đẹp, bởi vì nó cũng ngăn chặn một vòng lặp vô hạn từ khi tham số thứ 3 là '0'. – 4castle

+1

@ 4castle Tôi sẽ tranh luận khác. Nó không phải là mục đích của một tiện ích để cứu bạn khỏi chính mình. Không có gì ngăn cản bạn đặt 'do',' for', hoặc 'while' vào một vòng lặp vô hạn. Tại sao các chức năng chúng ta viết là khác nhau? Tôi thực sự thích các API với các cạnh cứng. Tôi cảm thấy hành vi mà chúng tôi không chỉ định là * không xác định *. Xem câu trả lời của tôi để làm rõ quan điểm của tôi. – naomik

+0

@NinaScholz, tất cả những điều đó sang một bên, đây là nếu không một câu trả lời rất tốt đẹp^_^ – naomik

0

Những câu trả lời đưa ra là tuyệt vời.Tôi chỉ muốn cung cấp cho bạn một ý tưởng về làm thế nào một cách tiếp cận chức năng hơn có thể giải quyết các nhiệm vụ:

// auxiliary functions: 
const append = (x, xs) => xs.concat([x]); 
const prepend = (x, xs) => [x].concat(xs); 

// main function 
const range = (x, y, step, acc = [], op = append) => 
step && step < 0 
    ? range(y, x, -step, acc, prepend) 
    : step && x <= y 
    ? range(x + step, y, step, op(x, acc), op) // tail call 
    : acc; 

console.log(range(1,5,1)); // [1,2,3,4,5] 
console.log(range(1,5,2)); // [1,3,5] 
console.log(range(1,5,6)); // [1] 
console.log(range(5,1,1)); // [] 
console.log(range(1,5,0)); // [] 
console.log(range(5,1,-1)); // [5,4,3,2,1] 
console.log(range(5,1,-2)); // [5,3,1] 
console.log(range(5,1,-6)); // [1] 
console.log(range(1,5,-1)); // [] 

Thuật toán:

  • acc = []op = append giá trị tham số mặc định (được thực hiện nếu bỏ qua trong các chức năng gọi)
  • step && step < 0 mạch ngắn nếu step là zero, nếu không kiểm tra nếu bước là âm
  • range(y, x, -step, acc, prepend) được gọi khi step là số âm và chuyển đổi tham số hóa range 's để step thể là tích cực (lưu ý rằng -step là tương đương với -(-1), được đánh giá để 1)
  • range(x + step, y, step, op(x, acc), op) trường hợp đệ quy đó có nghĩa là, chức năng tự gọi mình (lưu ý rằng op có thể là append hoặc prepend tùy thuộc vào dấu ban đầu của step, mà x được tăng step và nối/thêm vào phía trước acc)
  • trường hợp acc cơ sở mà dừng đệ quy và trả về mảng tích lũy
2

Một rất đơn giản một chiều (tăng dần), phạm vi bao gồm - đi x-y incrementing bởi 1 mỗi lần.

// range :: (Int, Int) -> [Int] 
 
const range = (x,y) => 
 
    x > y ? [] : [x, ...range(x + 1, y)]; 
 

 
console.log(range(1,4)); // [1,2,3,4] 
 
console.log(range(3,3)); // [3] 
 
console.log(range(6,3)); // []

Một thích ứng nhẹ có hỗ trợ hai chiều (ascending hoặc giảm dần) phạm vi - vẫn increments hay decrements bởi 1

// range :: (Int, Int) -> [Int] 
 
const range = (x,y) => { 
 
    if (x > y) 
 
    return range(y,x).reverse(); 
 
    else 
 
    return x === y ? [y] : [x, ...range(x + 1, y)]; 
 
} 
 

 
console.log(range(1,4)); // [1,2,3,4] 
 
console.log(range(3,3)); // [3] 
 
console.log(range(6,3)); // [6,5,4,3]

Một sự thích nghi khác sử dụng các hàm bậc cao hơn để kiểm soát nhiều hơn - điều này mang lại cho bạn hiệu quả bước/tăng thêm một số bạn đang tìm kiếm - tho này mạnh hơn vì nó cho phép bạn sử dụng hàm, t, để chọn giá trị tiếp theo.

const gte = x => y => y >= x; 
 
const lte = x => y => y <= x; 
 
const add = x => y => y + x; 
 
const sub = x => y => y - x; 
 

 
// range :: (Int, (Int -> Bool), (Int -> Int)) -> [Int] 
 
const range = (x, p, t) => { 
 
    if (p(x)) 
 
    return [x, ...range(t(x), p, t)]; 
 
    else 
 
    return []; 
 
}; 
 

 
console.log(range(2, lte(8), add(2))); // [2,4,6,8] 
 
console.log(range(9, gte(0), sub(3))); // [9,6,3,0] 
 
console.log(range(9, gte(0), sub(5))); // [9, 4] 
 

 
// very power. wow. 
 
const double = x => x + x; 
 
console.log(range(2, lte(50), double)); // [2,4,8,16,32]

Chức năng này có những rủi ro tương tự vốn có với forwhile - đó là tùy thuộc vào bạn để đảm bảo bạn không đặt nó vào một vòng lặp vô hạn.


quá tải chức năng

Cảnh báo: Esoteric, functionals không thực tế ở phía trước. Các thông tin sau đây chỉ được cung cấp cho niềm vui học tập của bạn.

Chức năng range cũng là một trong những trình diễn yêu thích của tôi về bộ kết hợp Y. Tôi sẽ chỉ cho bạn hai ví dụ ở đây.

ngây thơ range

const U = f => f (f); 
 
const Y = U (h => f => f (x => h (h) (f) (x))); 
 

 
const range = Y (f => acc => x => y => 
 
    x > y ? acc : f ([...acc, x]) (x + 1) (y) 
 
) ([]); 
 

 
console.log(range (3) (6)); // [3,4,5,6] 
 
console.log(range (6) (6)); // [6] 
 
console.log(range (9) (6)); // []

và bậc cao range

const U = f => f (f); 
 
const Y = U (h => f => f (x => h (h) (f) (x))); 
 

 
const lt = x => y => y < x; 
 
const gt = x => y => y > x; 
 
const add1 = x => x + 1; 
 
const sub1 = x => x - 1; 
 

 
const range = Y (f => acc => x => p => t => 
 
    p(x) ? f ([...acc, x]) (t(x)) (p) (t) : acc 
 
) ([]); 
 

 
console.log(range (3) (lt(6)) (add1)); // [3,4,5] 
 
console.log(range (6) (lt(6)) (add1)); // [] 
 
console.log(range (9) (gt(6)) (sub1)); // [9,8,7]

Điều gì là đẹp.

Các vấn đề liên quan