Cách viết nhỏ gọn (a + b == c hoặc a + c == b hoặc b + c == a)


136

Có cách nào nhỏ gọn hơn hoặc pythonic để viết biểu thức boolean

a + b == c or a + c == b or b + c == a

Tôi đến với

a + b + c in (2*a, 2*b, 2*c)

nhưng đó là một chút lạ.


16
Nhỏ gọn hơn? Có khả năng. Thêm Pythonic? Không có khả năng.
chepner

126
Làm cho bản thân tương lai của bạn một ưu tiên và giữ nó ở dạng ban đầu: Đó là điều duy nhất ngay lập tức cho biết mục đích của việc này. Đừng sửa đổi điều đó. Càng đơn giản thì tốt hơn phức tạp. Nếu việc thực hiện khó giải thích thì đó là một ý tưởng tồi.
chọc

21
Pythonic == không thể đọc được?
nhaarman

3
@wwii Họ không loại trừ lẫn nhau. Xem a = 0, b = 0, c = 0;)
Honza Brabec

1
Những gì @phresnel nói. Thay vì cố gắng "đơn giản hóa" biểu thức, hãy bọc nó trong một hàm với một tên mô tả.
Cephalepad

Câu trả lời:


206

Nếu chúng ta nhìn vào Zen của Python, hãy nhấn mạnh vào tôi:

Zen của Python, bởi Tim Peters

Đẹp thì tốt hơn xấu.
Rõ ràng là tốt hơn so với ngầm.
Đơn giản là tốt hơn phức tạp.
Phức tạp tốt hơn phức tạp.
Bằng phẳng là tốt hơn so với lồng nhau.
Thưa thì tốt hơn dày đặc.
Tính dễ đọc.
Trường hợp đặc biệt không đủ đặc biệt để phá vỡ các quy tắc.
Mặc dù thực tế đánh bại sự tinh khiết.
Lỗi không bao giờ nên âm thầm vượt qua.
Trừ khi im lặng rõ ràng.
Trước sự mơ hồ, hãy từ chối sự cám dỗ để đoán.
Nên có một-- và tốt nhất là chỉ có một cách rõ ràng để làm điều đó.
Mặc dù cách đó ban đầu có thể không rõ ràng trừ khi bạn là người Hà Lan.
Bây giờ tốt hơn bao giờ hết.
Mặc dù không bao giờ thường tốt hơnngay bây giờ
Nếu việc thực hiện khó giải thích, đó là một ý tưởng tồi.
Nếu việc thực hiện dễ giải thích, nó có thể là một ý tưởng tốt.
Không gian tên là một ý tưởng tuyệt vời - hãy làm nhiều hơn nữa!

Giải pháp Pythonic nhất là giải pháp rõ ràng nhất, đơn giản nhất và dễ giải thích nhất:

a + b == c or a + c == b or b + c == a

Thậm chí tốt hơn, bạn thậm chí không cần biết Python để hiểu mã này! Đó là điều đó dễ dàng. Đây là, không có đặt phòng, giải pháp tốt nhất. Bất cứ điều gì khác là thủ dâm trí tuệ.

Hơn nữa, đây có thể là giải pháp hiệu quả tốt nhất, vì nó là giải pháp duy nhất trong số tất cả các đề xuất ngắn mạch. Nếu a + b == c, chỉ một bổ sung và so sánh được thực hiện.


11
Thậm chí tốt hơn, ném vào một số dấu ngoặc đơn để làm cho ý định rõ ràng.
Bryan Oakley

3
Ý định đã rõ ràng mà không có dấu ngoặc đơn. Dấu ngoặc đơn sẽ làm cho nó khó đọc hơn - tại sao tác giả sử dụng dấu ngoặc đơn khi quyền ưu tiên đã bao gồm điều này?
Miles Rout

1
Một lưu ý khác về việc cố gắng quá thông minh: bạn có thể đưa ra các lỗi không lường trước được do thiếu các điều kiện mà bạn không xem xét. Nói cách khác, bạn có thể nghĩ rằng giải pháp nhỏ gọn mới của mình là tương đương, nhưng không phải trong mọi trường hợp. Trừ khi có một lý do thuyết phục để mã hóa khác (hiệu suất, hạn chế bộ nhớ, v.v.), sự rõ ràng là vua.
Rob Craig

Nó phụ thuộc vào những gì công thức là cho. Nhìn vào 'Rõ ràng là tốt hơn so với ngầm', có thể là cách tiếp cận 'sắp xếp trước' thể hiện rõ hơn những gì chương trình đang làm, hoặc một trong những cách khác. Tôi không nghĩ chúng ta có thể đánh giá từ câu hỏi.
Thomas Ahle

101

Giải ba đẳng thức cho a:

a in (b+c, b-c, c-b)

4
Vấn đề duy nhất với điều này là tác dụng phụ. Nếu b hoặc c là các biểu thức phức tạp hơn, chúng sẽ được chạy nhiều lần.
Silvio Mayolo

3
@Kroltan Quan điểm của tôi là tôi thực sự đã trả lời câu hỏi của anh ấy, yêu cầu một đại diện "nhỏ gọn hơn". Xem: en.m.wikipedia.org/wiki/Short-circuit_ev Assessment
Alex Varga

24
Bất cứ ai đọc mã này có thể sẽ nguyền rủa bạn vì "thông minh".
Karoly Horvath

5
@SilvioMayolo Điều tương tự cũng đúng với bản gốc
Izkata

1
@AlexVarga, "Quan điểm của tôi là tôi thực sự đã trả lời câu hỏi của anh ấy". Bạn đã làm; nó sử dụng ít hơn 30% ký tự (đặt khoảng trắng giữa các toán tử). Tôi đã không cố nói câu trả lời của bạn là sai, chỉ bình luận về cách nó thành ngữ (pythonic). Câu trả lời tốt đẹp.
Paul Draper

54

Python có một anyhàm thực hiện ortrên tất cả các phần tử của chuỗi. Ở đây tôi đã chuyển đổi tuyên bố của bạn thành một bộ 3 yếu tố.

any((a + b == c, a + c == b, b + c == a))

Lưu ý rằng đó orlà ngắn mạch, vì vậy nếu tính toán các điều kiện riêng lẻ là tốn kém, có thể tốt hơn để giữ cấu trúc ban đầu của bạn.


2
any()all()ngắn mạch quá.
TigerhawkT3

42
@ TigerhawkT3 Không phải trong trường hợp này; ba biểu thức sẽ được đánh giá trước khi bộ dữ liệu tồn tại và bộ dữ liệu sẽ tồn tại trước anycả khi chạy.
chọc

13
Ah tôi thấy. Tôi đoán nó chỉ khi có một máy phát điện hoặc trình vòng lặp lười biếng tương tự ở đó.
TigerhawkT3

4
anyall"đoản mạch" quá trình kiểm tra vòng lặp được đưa ra; nhưng nếu iterable đó là một chuỗi chứ không phải là một trình tạo, thì nó đã được đánh giá đầy đủ trước khi xảy ra lệnh gọi hàm .
Karl Knechtel

Điều này có lợi thế là dễ dàng phân chia thành nhiều dòng (thụt hai lần các đối số thành any, thụt lề một lần ):trong ifcâu lệnh), giúp ích rất nhiều cho khả năng đọc khi toán học được tham gia
Izkata

40

Nếu bạn biết bạn chỉ đang xử lý các số dương, điều này sẽ hoạt động và khá sạch sẽ:

a, b, c = sorted((a, b, c))
if a + b == c:
    do_stuff()

Như tôi đã nói, điều này chỉ hoạt động cho các số dương; nhưng nếu bạn biết họ sẽ tích cực, thì đây là một giải pháp IMO rất dễ đọc, thậm chí trực tiếp trong mã trái ngược với chức năng.

Bạn có thể làm điều này, có thể làm một chút tính toán lặp đi lặp lại; nhưng bạn đã không chỉ định hiệu suất làm mục tiêu của mình:

from itertools import permutations

if any(x + y == z for x, y, z in permutations((a, b, c), 3)):
    do_stuff()

Hoặc không có permutations()và khả năng tính toán lặp đi lặp lại:

if any(x + y == z for x, y, z in [(a, b, c), (a, c, b), (b, c, a)]:
    do_stuff()

Tôi có thể sẽ đặt điều này, hoặc bất kỳ giải pháp nào khác, vào một chức năng. Sau đó, bạn có thể chỉ cần gọi sạch hàm trong mã của bạn.

Cá nhân, trừ khi tôi cần sự linh hoạt hơn từ mã, tôi sẽ chỉ sử dụng phương thức đầu tiên trong câu hỏi của bạn. Thật đơn giản và hiệu quả. Tôi vẫn có thể đặt nó vào một chức năng:

def two_add_to_third(a, b, c):
    return a + b == c or a + c == b or b + c == a

if two_add_to_third(a, b, c):
    do_stuff()

Đó là Pythonic đẹp, và đó hoàn toàn có thể là cách hiệu quả nhất để thực hiện (chức năng bổ sung gọi sang một bên); mặc dù bạn không nên lo lắng quá nhiều về hiệu suất, trừ khi nó thực sự gây ra vấn đề.


đặc biệt nếu chúng ta có thể giả sử a, b, c đều không âm.
cphlewis

Tôi thấy cụm từ "không phải lúc nào cũng hoạt động" hơi khó hiểu. Giải pháp đầu tiên chỉ hoạt động nếu bạn biết chắc chắn rằng các số của bạn không âm. Chẳng hạn với (a, b, c) = (-3, -2, -1) bạn có a + b! = C nhưng b + c = a. Các trường hợp tương tự với (-1, 1, 2) và (-2, -1, 1).
báo

@usernumber, bạn biết đấy, tôi nhận thấy điều đó sớm hơn; không chắc tại sao tôi không sửa nó.
Cyphase

Giải pháp hàng đầu của bạn không hoạt động đối với một nhóm lớn đầu vào, trong khi đề xuất của OP hoạt động cho tất cả các đầu vào. Làm thế nào là "không hoạt động" nhiều Pythonic hơn "làm việc"?
Barry

3
Ôi chao. " Nếu bạn biết bạn chỉ đang xử lý các số dương , điều này sẽ hoạt động và khá sạch sẽ". Tất cả những người khác làm việc cho bất kỳ số nào, nhưng nếu bạn biết bạn chỉ đang xử lý các số dương , thì số trên rất dễ đọc / Pythonic IMO.
Cyphase

17

Nếu bạn sẽ chỉ sử dụng ba biến thì phương thức ban đầu của bạn:

a + b == c or a + c == b or b + c == a

Đã rất pythonic.

Nếu bạn có kế hoạch sử dụng nhiều biến hơn thì phương pháp suy luận của bạn với:

a + b + c in (2*a, 2*b, 2*c)

Rất thông minh nhưng hãy nghĩ về lý do tại sao. Tại sao điều này làm việc?
Thông qua một số số học đơn giản, chúng ta thấy rằng:

a + b = c
c = c
a + b + c == c + c == 2*c
a + b + c == 2*c

Và điều này sẽ phải giữ đúng đối với một trong hai a, b, hoặc c, có nghĩa là có nó sẽ tương đương 2*a, 2*bhoặc 2*c. Điều này sẽ đúng với bất kỳ số lượng biến.

Vì vậy, một cách tốt để viết điều này một cách nhanh chóng là chỉ cần có một danh sách các biến của bạn và kiểm tra tổng của chúng dựa vào danh sách các giá trị nhân đôi.

values = [a,b,c,d,e,...]
any(sum(values) in [2*x for x in values])

Bằng cách này, để thêm nhiều biến vào phương trình, tất cả những gì bạn phải làm là chỉnh sửa danh sách giá trị của mình bằng các biến mới 'n', không viết phương trình 'n'


4
Thế còn a=-1, b=-1thì c=-2, sau đó a+b=c, nhưng a+b+c = -42*max(a,b,c)-2
Eric Renouf

Cảm ơn bạn đó là sự thật, tôi sẽ cần phải sử dụng abs. Thực hiện điều chỉnh đó ngay bây giờ.
ThatGuyRussell

2
Sau khi thực hiện với nửa tá abs()cuộc gọi, nó là Pythonic so với đoạn trích của OP (tôi thực sự gọi nó là ít đọc hơn đáng kể).
TigerhawkT3

Điều đó rất đúng, tôi sẽ điều chỉnh ngay bây giờ
ThatGuyRussell

1
@ThatGuyRussell Để đoản mạch, bạn sẽ muốn sử dụng một máy phát điện ... đại loại như vậy any(sum(values) == 2*x for x in values), theo cách đó bạn sẽ không phải thực hiện tất cả các thao tác nhân đôi lên phía trước, khi cần thiết.
Barry

12

Đoạn mã sau có thể được sử dụng để so sánh lặp lại từng phần tử với tổng của các phần tử khác, được tính từ tổng của toàn bộ danh sách, ngoại trừ phần tử đó.

 l = [a,b,c]
 any(sum(l)-e == e for e in l)

2
Rất tuyệt :) Tôi nghĩ rằng nếu bạn xóa []dấu ngoặc khỏi dòng thứ hai, điều này thậm chí sẽ ngắn mạch như ban đầu với or...
psmears

1
về cơ bản any(a + b + c == 2*x for x in [a, b, c]), khá gần với đề xuất của OP
njzk2

Điều đó là tương tự, tuy nhiên phương pháp này mở rộng cho bất kỳ số lượng biến. Tôi kết hợp đề xuất của @psmears về ngắn mạch.
Arcanum

10

Đừng thử và đơn giản hóa nó. Thay vào đó, hãy đặt tên cho những gì bạn đang làm với một chức năng:

def any_two_sum_to_third(a, b, c):
  return a + b == c or a + c == b or b + c == a

if any_two_sum_to_third(foo, bar, baz):
  ...

Thay thế điều kiện bằng một cái gì đó "thông minh" có thể làm cho nó ngắn hơn, nhưng nó sẽ không làm cho nó dễ đọc hơn. Tuy nhiên, việc để lại nó không dễ đọc lắm, bởi vì thật khó để biết tại sao bạn lại kiểm tra ba điều kiện đó trong nháy mắt. Điều này làm cho nó hoàn toàn rõ ràng những gì bạn đang kiểm tra.

Về hiệu suất, phương pháp này không thêm chi phí cho một cuộc gọi chức năng, nhưng không bao giờ hy sinh khả năng đọc cho hiệu suất trừ khi bạn thấy có một nút cổ chai mà bạn nhất định phải sửa. Và luôn luôn đo lường, vì một số triển khai thông minh có khả năng tối ưu hóa và thực hiện một số lời gọi hàm trong một số trường hợp.


1
Các hàm chỉ nên được viết nếu bạn muốn sử dụng cùng một mã ở nhiều điểm hoặc nếu mã phức tạp. Không có đề cập đến việc tái sử dụng mã trong câu hỏi ban đầu và việc viết một hàm cho một dòng mã không chỉ là quá mức cần thiết mà nó còn thực sự làm suy yếu khả năng đọc.
Igor Levicki

5
Đến từ trường phái FP, tôi gần như không đồng ý hoàn toàn và nói rằng các hàm một dòng được đặt tên tốt là một trong những công cụ tốt nhất để tăng khả năng đọc mà bạn sẽ tìm thấy. Tạo một hàm bất cứ khi nào các bước bạn thực hiện để làm điều gì đó không ngay lập tức mang lại sự rõ ràng cho những gì bạn đang làm, vì tên của hàm cho phép bạn chỉ định những gì tốt hơn bất kỳ nhận xét nào có thể.
Jack

Bất cứ trường nào bạn viện dẫn đều là xấu khi tuân thủ một cách mù quáng một bộ quy tắc. Phải nhảy sang một phần khác của nguồn để đọc rằng một dòng mã được ẩn bên trong một hàm chỉ để có thể xác minh rằng nó thực sự làm những gì nó nói trong tên, và sau đó phải chuyển về vị trí của một cuộc gọi đến hãy chắc chắn rằng bạn đang truyền tham số chính xác là chuyển đổi ngữ cảnh hoàn toàn không cần thiết. Theo ý kiến ​​của tôi, việc đó làm suy yếu cả khả năng đọc và quy trình làm việc. Cuối cùng, cả tên hàm và bình luận mã đều không phải là sự thay thế phù hợp cho tài liệu mã.
Igor Levicki

9

Con trăn 3:

(a+b+c)/2 in (a,b,c)
(a+b+c+d)/2 in (a,b,c,d)
...

Nó chia tỷ lệ cho bất kỳ số lượng biến:

arr = [a,b,c,d,...]
sum(arr)/2 in arr

Tuy nhiên, nói chung tôi đồng ý rằng trừ khi bạn có nhiều hơn ba biến, phiên bản gốc dễ đọc hơn.


3
Điều này trả về kết quả không chính xác cho một số đầu vào do lỗi làm tròn điểm nổi.
pts

Bộ phận nên được tránh vì lý do hiệu suất và chính xác.
Igor Levicki

1
@pts Sẽ không có bất kỳ triển khai nào trả về kết quả không chính xác vì làm tròn dấu phẩy động? Thậm chí a + b == c
osundblad

@osundblad: Nếu a, b và c là ints, thì (a + b + c) / 2 làm tròn số (và có thể trả về kết quả không chính xác), nhưng a + b == c là chính xác.
pts

3
chia cho 2 chỉ đơn giản là giảm số mũ xuống một, do đó, sẽ chính xác cho bất kỳ số nguyên nào nhỏ hơn 2 ^ 53 (phần phân số của số float trong python) và đối với số nguyên lớn hơn bạn có thể sử dụng số thập phân . Ví dụ: để kiểm tra các số nguyên ít hơn 2 ^ 30 chạy[x for x in range(pow(2,30)) if x != ((x * 2)/ pow(2,1))]
Vitalii Fedorenko

6
(a+b-c)*(a+c-b)*(b+c-a) == 0

Nếu tổng của hai số hạng bất kỳ bằng số hạng thứ ba, thì một trong các yếu tố sẽ bằng 0, làm cho toàn bộ sản phẩm bằng không.


Tôi đã suy nghĩ chính xác điều tương tự nhưng tôi không thể phủ nhận rằng đề xuất ban đầu của anh ấy sạch sẽ hơn ...
user541686

@Mehrdad - Chắc chắn. Nó thực sự không khác gì so(a+b<>c) && (a+c<>b) && (b+c<>a) == false
mbeckish

Chỉ là phép nhân đắt hơn các biểu thức logic và số học cơ bản.
Igor Levicki

@IgorLevicki - Có, mặc dù đó là mối quan tâm tối ưu hóa RẤT sớm. Điều này sẽ được thực hiện hàng chục ngàn lần mỗi giây? Nếu có, thì có lẽ bạn sẽ muốn nhìn vào một cái gì đó khác.
mbeckish

@mbeckish - Tại sao bạn nghĩ rằng nó là sớm? Mã nên được viết với tối ưu hóa trong tâm trí, không được tối ưu hóa như là một suy nghĩ sau. Một ngày nào đó, một số thực tập sinh sẽ sao chép đoạn mã này và dán nó vào một số vòng lặp quan trọng về hiệu năng trên nền tảng nhúng, sau đó sẽ chạy trên hàng triệu thiết bị không nhất thiết phải chậm vì những gì nó làm, nhưng có thể gây lãng phí nhiều pin hơn. Viết mã như vậy chỉ khuyến khích thực hành mã hóa xấu. Theo tôi, điều OP nên hỏi là liệu có cách nào để tối ưu hóa biểu thức logic đó hay không.
Igor Levicki

6

Còn về

a == b + c or abs(a) == abs(b - c)

Lưu ý rằng điều này sẽ không hoạt động nếu các biến không được ký.

Từ quan điểm tối ưu hóa mã (ít nhất là trên nền tảng x86), đây dường như là giải pháp hiệu quả nhất.

Trình biên dịch hiện đại sẽ thực hiện cả hai lệnh gọi hàm abs () và tránh kiểm tra dấu hiệu và nhánh có điều kiện tiếp theo bằng cách sử dụng một chuỗi thông minh các lệnh CDQ, XOR và SUB . Do đó, mã mức cao ở trên sẽ được biểu diễn chỉ bằng các hướng dẫn ALU có độ trễ thấp, thông lượng cao và chỉ có hai điều kiện.


Và tôi nghĩ fabs()có thể được sử dụng cho floatcác loại;).
shA.t

4

Giải pháp được cung cấp bởi Alex Varga "a in (b + c, bc, cb)" nhỏ gọn và đẹp về mặt toán học, nhưng tôi thực sự sẽ không viết mã theo cách đó bởi vì nhà phát triển tiếp theo sẽ không hiểu ngay mục đích của mã .

Giải pháp của Mark Ransom

any((a + b == c, a + c == b, b + c == a))

rõ ràng hơn nhưng không ngắn gọn hơn

a + b == c or a + c == b or b + c == a

Khi viết mã mà người khác sẽ phải xem, hoặc tôi sẽ phải nhìn vào một thời gian dài sau đó khi tôi quên mất những gì tôi đã nghĩ khi tôi viết nó, quá ngắn hoặc thông minh có xu hướng gây hại nhiều hơn là tốt. Mã nên được đọc. Vì vậy, cô đọng là tốt, nhưng không ngắn gọn đến nỗi các lập trình viên tiếp theo không thể hiểu nó.


Câu hỏi trung thực: tại sao mọi người luôn cho rằng lập trình viên tiếp theo sẽ là một thằng ngốc không có khả năng đọc mã? Cá nhân tôi thấy ý kiến ​​đó xúc phạm. Nếu mã phải được viết rõ ràng cho mọi lập trình viên, thì điều đó ngụ ý rằng chúng tôi là một nghề nghiệp đang phục vụ cho mẫu số chung thấp nhất, ít kỹ năng nhất trong số chúng tôi. Nếu chúng ta tiếp tục làm điều đó, làm thế nào họ sẽ cải thiện kỹ năng cá nhân của họ? Tôi không thấy điều này trong các ngành nghề khác. Lần cuối cùng bạn nhìn thấy một nhà soạn nhạc viết một bản nhạc đơn giản chỉ để mọi nhạc sĩ có thể chơi nó bất kể trình độ kỹ năng là khi nào?
Igor Levicki

6
Vấn đề là ngay cả các lập trình viên cũng bị hạn chế năng lượng tinh thần, vì vậy bạn có muốn dành năng lượng tinh thần hạn chế của mình cho thuật toán và các khía cạnh cấp cao hơn của chương trình hay tìm hiểu xem một dòng mã phức tạp nào có nghĩa là khi nó có thể được biểu thị đơn giản hơn ? Lập trình rất khó, vì vậy đừng làm khó bản thân một cách không cần thiết, giống như một vận động viên Olympic sẽ không chạy đua với một chiếc ba lô nặng chỉ vì họ có thể. Như Steve McConell đã nói trong Code Complete 2, khả năng đọc là một trong những khía cạnh quan trọng nhất của mã.
Paul J Abernathy

2

Yêu cầu là nhỏ gọn hơn HOẶC nhiều pythonic hơn - Tôi đã thử với tay nhỏ gọn hơn.

được

import functools, itertools
f = functools.partial(itertools.permutations, r = 3)
def g(x,y,z):
    return x + y == z

Đây là 2 ký tự ít hơn bản gốc

any(g(*args) for args in f((a,b,c)))

kiểm tra với:

assert any(g(*args) for args in f((a,b,c))) == (a + b == c or a + c == b or b + c == a)

ngoài ra, được đưa ra:

h = functools.partial(itertools.starmap, g)

Điều này là tương đương

any(h(f((a,b,c))))

Chà, đó là hai ký tự ngắn hơn bản gốc, nhưng không phải là ký tự mà OP đưa ra ngay sau đó, mà anh ta nói rằng anh ta hiện đang sử dụng. Bản gốc cũng bao gồm rất nhiều khoảng trắng, cái này bỏ qua bất cứ khi nào có thể. Ngoài ra còn có vấn đề nhỏ về chức năng g()mà bạn phải xác định để làm việc này. Với tất cả những điều đó, tôi muốn nói rằng nó lớn hơn đáng kể.
TigerhawkT3

@ TigerhawkT3, tôi diễn giải nó như một yêu cầu cho một biểu thức / dòng ngắn hơn. xem chỉnh sửa để cải thiện hơn nữa .
wwii

4
Tên hàm rất xấu, chỉ thích hợp cho một mã golf.
0xc0de

@ 0xc0de - xin lỗi tôi không chơi. Thích hợp có thể khá chủ quan và phụ thuộc vào hoàn cảnh - nhưng tôi sẽ trì hoãn cộng đồng.
wwii

Tôi không thấy làm thế nào nhỏ gọn hơn khi nó có nhiều ký tự hơn mã gốc.
Igor Levicki

1

Tôi muốn trình bày những gì tôi thấy là câu trả lời pythonic nhất :

def one_number_is_the_sum_of_the_others(a, b, c):
    return any((a == b + c, b == a + c, c == a + b))

Trường hợp chung, không được tối ưu hóa:

def one_number_is_the_sum_of_the_others(numbers):
    for idx in range(len(numbers)):
        remaining_numbers = numbers[:]
        sum_candidate = remaining_numbers.pop(idx)
        if sum_candidate == sum(remaining_numbers):
            return True
    return False 

Về mặt Zen của Python, tôi nghĩ rằng các câu được nhấn mạnh được theo dõi nhiều hơn so với câu trả lời khác:

Zen của Python, bởi Tim Peters

Đẹp thì tốt hơn xấu.
Rõ ràng là tốt hơn so với ngầm.
Đơn giản là tốt hơn phức tạp.
Phức tạp tốt hơn phức tạp.
Bằng phẳng là tốt hơn so với lồng nhau.
Thưa thì tốt hơn dày đặc.
Tính dễ đọc.
Trường hợp đặc biệt không đủ đặc biệt để phá vỡ các quy tắc.
Mặc dù thực tế đánh bại sự tinh khiết.
Lỗi không bao giờ nên âm thầm vượt qua.
Trừ khi im lặng rõ ràng.
Trước sự mơ hồ, hãy từ chối sự cám dỗ để đoán.
Nên có một-- và tốt nhất là chỉ có một cách rõ ràng để làm điều đó.
Mặc dù cách đó ban đầu có thể không rõ ràng trừ khi bạn là người Hà Lan.
Bây giờ tốt hơn bao giờ hết.
Mặc dù không bao giờ thường tốt hơnngay bây giờ
Nếu việc thực hiện khó giải thích, đó là một ý tưởng tồi.
Nếu việc thực hiện dễ giải thích, nó có thể là một ý tưởng tốt.
Không gian tên là một ý tưởng tuyệt vời - hãy làm nhiều hơn nữa!


1

Như một thói quen cũ của lập trình của tôi, tôi nghĩ rằng việc đặt biểu thức phức tạp ở bên phải trong một mệnh đề có thể làm cho nó dễ đọc hơn như thế này:

a == b+c or b == a+c or c == a+b

Cộng ():

((a == b+c) or (b == a+c) or (c == a+b))

Và tôi cũng nghĩ rằng việc sử dụng nhiều dòng cũng có thể tạo ra nhiều giác quan như thế này:

((a == b+c) or 
 (b == a+c) or 
 (c == a+b))

0

Nói một cách chung chung,

m = a+b-c;
if (m == 0 || m == 2*a || m == 2*b) do_stuff ();

nếu, thao tác với một biến đầu vào là OK cho bạn,

c = a+b-c;
if (c==0 || c == 2*a || c == 2*b) do_stuff ();

nếu bạn muốn khai thác bằng cách sử dụng hack, bạn có thể sử dụng "!", ">> 1" và "<< 1"

Tôi đã tránh phân chia mặc dù nó cho phép sử dụng để tránh hai phép nhân để tránh các lỗi làm tròn. Tuy nhiên, kiểm tra tràn


0
def any_sum_of_others (*nums):
    num_elements = len(nums)
    for i in range(num_elements):
        discriminating_map = map(lambda j: -1 if j == i else 1, range(num_elements))
        if sum(n * u for n, u in zip(nums, discriminating_map)) == 0:
            return True
    return False

print(any_sum_of_others(0, 0, 0)) # True
print(any_sum_of_others(1, 2, 3)) # True
print(any_sum_of_others(7, 12, 5)) # True
print(any_sum_of_others(4, 2, 2)) # True
print(any_sum_of_others(1, -1, 0)) # True
print(any_sum_of_others(9, 8, -4)) # False
print(any_sum_of_others(4, 3, 2)) # False
print(any_sum_of_others(1, 1, 1, 1, 4)) # True
print(any_sum_of_others(0)) # True
print(any_sum_of_others(1)) # False

Các hàm chỉ nên được viết nếu bạn muốn sử dụng cùng một mã ở nhiều điểm hoặc nếu mã phức tạp. Không có đề cập đến việc tái sử dụng mã trong câu hỏi ban đầu và việc viết một hàm cho một dòng mã không chỉ là quá mức cần thiết mà nó còn thực sự làm suy yếu khả năng đọc.
Igor Levicki

Tôi không đồng ý rằng nó làm suy yếu khả năng đọc; nếu bạn chọn một tên phù hợp, nó có thể cải thiện khả năng đọc (nhưng tôi không đại diện cho chất lượng của tên tôi đã chọn trong câu trả lời này). Ngoài ra, có thể hữu ích để đặt tên cho một khái niệm, mà bạn sẽ phải làm miễn là bạn buộc bản thân phải đặt tên tốt cho chức năng của mình. Chức năng là tốt. Về việc chức năng có đủ phức tạp để hưởng lợi từ việc được gói gọn trong một chức năng hay không, đó là một đánh giá chủ quan.
Hammerite
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.