วิธีเขียนนิพจน์ ternary operator (aka if) โดยไม่ต้องทำซ้ำ


105

ตัวอย่างเช่นสิ่งนี้:

var value = someArray.indexOf(3) !== -1 ? someArray.indexOf(3) : 0

มีวิธีเขียนที่ดีกว่านี้ไหม อีกครั้งฉันไม่ได้ต้องการคำตอบสำหรับคำถามที่แน่นอนข้างต้นเป็นเพียงตัวอย่างของเวลาที่คุณอาจมีตัวถูกดำเนินการซ้ำ ๆ ในนิพจน์ตัวดำเนินการที่เกี่ยวข้อง ...


2
ดังนั้นifและไม่ใช่if/else
zer00ne เมื่อ

53
just an example of when you might have repeated things in the ternaryอย่าทำนิพจน์ที่คำนวณซ้ำ นั่นคือสิ่งที่เป็นตัวแปรสำหรับ
vol7ron

4
เราจะทราบได้อย่างไรว่าสิ่ง3นั้นไม่อยู่ที่ดัชนี0ของsomeArray?
แขก 271314

3
เป้าหมายของคุณที่นี่คืออะไร? คุณกำลังพยายามลดความยาวบรรทัดหรือโดยเฉพาะอย่างยิ่งพยายามที่จะหลีกเลี่ยงการทำซ้ำของตัวแปรใน ternary? อดีตเป็นไปได้อย่างหลังไม่ใช่ (อย่างน้อยก็ไม่ใช้ ternaries)
asgallant

5
ทำไมไม่ใช้Math.max(someArray.indexOf(3), 0)แทน?
301_Moved_ ถาวร

คำตอบ:


176

โดยส่วนตัวแล้วฉันพบว่าวิธีที่ดีที่สุดในการทำสิ่งนี้ยังคงเป็นifคำพูดเก่าที่ดี:

var value = someArray.indexOf(3);
if (value === -1) {
  value = 0;
}

32
เพื่อความชัดเจนคำตอบนี้สนับสนุนการใช้ตัวแปรเพื่อจัดเก็บผลลัพธ์ระดับกลางไม่ใช่การใช้ifคำสั่งแทน ternary คำสั่ง Ternary มักมีประโยชน์ในการเลือกเป็นส่วนหนึ่งของนิพจน์
Triptych

4
@Triptych: ดูอีกที มันไม่ใช้ตัวแปรกลางเลย แต่จะกำหนดผลลัพธ์ให้กับตัวแปรสุดท้ายโดยตรงแล้วเขียนทับหากตรงตามเงื่อนไข
slebetman

14
ไม่ถูกต้อง ค่าที่เก็บไว้valueหลังบรรทัดแรกเป็นค่ากลาง ไม่มีค่าที่ถูกต้องซึ่งได้รับการแก้ไขแล้วในบรรทัดถัดไปจึงเป็นค่ากลาง หลังจากifคำสั่งสรุปว่าvalueมีค่าที่ถูกต้องเท่านั้น ternary ใน OP เป็นทางออกที่ดีกว่าเนื่องจากไม่เคยเข้าสู่สถานะกลาง
Jack Aidley

44
@JackAidley: "ternary ใน OP เป็นทางออกที่ดีกว่าเพราะมันไม่เคยเข้าสู่สถานะกลาง" - ฉันจะต้องไม่เห็นด้วย สิ่งนี้อ่านได้ง่ายกว่ารหัสของ OP และเป็นสำนวนทั้งหมด นอกจากนี้ยังทำให้ข้อบกพร่องในตรรกะของ OP ชัดเจนขึ้นสำหรับฉันอีกเล็กน้อย (กล่าวคือจะเกิดอะไรขึ้นถ้า indexOf () ส่งคืนศูนย์คุณจะแยกแยะศูนย์ "จริง" ออกจากศูนย์ "ไม่พบ" ได้อย่างไร)
Kevin

2
สิ่งนี้ใกล้เคียงกับสิ่งที่ฉันจะทำยกเว้นที่valueนี่จะกลายพันธุ์ทางเทคนิคซึ่งฉันพยายามหลีกเลี่ยง
Dave Cousineau

102

รหัสควรอ่านได้ดังนั้นการกระชับไม่ควรหมายถึงการลดต้นทุนไม่ว่าจะด้วยต้นทุนใดก็ตามเพราะคุณควรโพสต์ใหม่ไปที่https://codegolf.stackexchange.com/ดังนั้นฉันขอแนะนำให้ใช้ตัวแปรท้องถิ่นตัวที่สองที่ตั้งชื่อindexเพื่อเพิ่มความเข้าใจในการอ่านให้มากที่สุด ( ด้วยต้นทุนรันไทม์ที่น้อยที่สุดฉันทราบ):

var index = someArray.indexOf( 3 );
var value = index == -1 ? 0 : index;

แต่ถ้าคุณอยากตัดความรู้สึกนี้ออกไปเพราะคุณเป็นพวกซาดิสม์ที่โหดร้ายกับเพื่อนร่วมงานหรือผู้ทำงานร่วมกันในโครงการคุณสามารถใช้ได้ 4 วิธีดังนี้

1: ตัวแปรชั่วคราวในไฟล์ varคำสั่ง

คุณสามารถใช้varความสามารถของคำสั่งเพื่อกำหนด (และกำหนด) ตัวแปรชั่วคราวตัวที่สองindexเมื่อคั่นด้วยลูกน้ำ:

var index = someArray.indexOf(3), value = index !== -1 ? index: 0;

2: ฟังก์ชันที่ไม่ระบุตัวตนที่ดำเนินการเอง

อีกทางเลือกหนึ่งคือฟังก์ชันที่ไม่ระบุตัวตนที่ดำเนินการเอง:

// Traditional syntax:
var value = function( x ) { return x !== -1 ? x : 0 }( someArray.indexOf(3) );

// ES6 syntax:
var value = ( x => x !== -1 ? x : 0 )( someArray.indexOf(3) );

3: ตัวดำเนินการจุลภาค

นอกจากนี้ยังมี "ตัวดำเนินการลูกน้ำ" ที่น่าอับอายซึ่ง JavaScript รองรับซึ่งมีอยู่ใน C และ C ++ ด้วย

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator

คุณสามารถใช้ตัวดำเนินการลูกน้ำเมื่อคุณต้องการรวมหลายนิพจน์ในตำแหน่งที่ต้องใช้นิพจน์เดียว

คุณสามารถใช้เพื่อแนะนำผลข้างเคียงในกรณีนี้โดยกำหนดใหม่เป็นvalue:

var value = ( value = someArray.indexOf(3), value !== -1 ? value : 0 );

สิ่งนี้ใช้งานได้เนื่องจากvar valueถูกตีความก่อน (เนื่องจากเป็นคำสั่ง) จากนั้นจึงเป็นการกำหนดทางซ้ายสุดด้านในสุดvalueและทางขวามือของตัวดำเนินการลูกน้ำจากนั้นตัวดำเนินการตามกฎหมายทั้งหมด - JavaScript ที่ถูกกฎหมาย

4: กำหนดใหม่ในนิพจน์ย่อย

ผู้แสดงความคิดเห็น @IllusiveBrian ชี้ให้เห็นว่าการใช้ตัวดำเนินการลูกน้ำ (ในตัวอย่างก่อนหน้านี้) ไม่จำเป็นหากใช้การกำหนดให้valueเป็นนิพจน์ย่อยในวงเล็บ:

var value = ( ( value = someArray.indexOf(3) ) !== -1 ? value : 0 );

โปรดทราบว่าการใช้เชิงลบในนิพจน์เชิงตรรกะอาจทำให้มนุษย์ปฏิบัติตามได้ยากขึ้นดังนั้นตัวอย่างทั้งหมดข้างต้นสามารถทำให้อ่านง่ายขึ้นโดยเปลี่ยนidx !== -1 ? x : yเป็นidx == -1 ? y : x:

var value = ( ( value = someArray.indexOf(3) ) == -1 ? 0 : value );

98
ทั้งหมดนี้เป็นรูปแบบของการเข้ารหัสที่ "ฉลาด" ซึ่งจะทำให้ฉันจ้องไปที่มันสักสองสามวินาทีก่อนที่จะคิดว่า "ฮะฉันเดาว่าได้ผล" พวกเขาไม่ได้ช่วยเรื่องความชัดเจนและเนื่องจากโค้ดถูกอ่านมากกว่าที่เขียนจึงสำคัญกว่า
Gavin S.Yancey

18
@ g.rocket approach 1 สามารถอ่านได้และชัดเจน 100% และเป็นวิธีเดียวที่จะไปหากคุณต้องการหลีกเลี่ยงการทำซ้ำ (ซึ่งอาจเป็นอันตรายได้หากคุณเรียกใช้ฟังก์ชันที่ซับซ้อนและมีปัญหาแทนที่จะเป็นแบบธรรมดาindefOf)
edc65

5
เห็นด้วยอันดับ 1 สามารถอ่านได้และบำรุงรักษาได้มากส่วนอีกสองรายการไม่มากนัก
ให้อภัย

6
สำหรับ # 3 ฉันเชื่อว่าคุณสามารถทำให้ง่ายขึ้นvar value = ((value = someArray.indexOf(3)) === -1 ? 0 : value);แทนที่จะใช้ลูกน้ำ
IllusiveBrian

2
ในตัวอย่างที่สองฟังก์ชันที่ไม่ระบุชื่อที่ดำเนินการเองคุณสามารถละเว้นวงเล็บจากฟังก์ชันลูกศรได้ var value = ( x => x !== -1 ? x : 0 ) ( arr.indexOf(3) );เนื่องจากเป็นเพียงพารามิเตอร์เดียว
Alex Char

54

สำหรับตัวเลข

คุณสามารถใช้Math.max()ฟังก์ชัน

var value = Math.max( someArray.indexOf('y'), 0 );

มันจะรักษาขอบเขตของผลลัพธ์ตั้งแต่0จนถึงผลลัพธ์แรกมากกว่า0ถ้าเป็นเช่นนั้น และถ้าผลลัพธ์จากindexOfคือ-1มันจะส่งกลับ 0 เมื่อมากกว่า-1เป็นมากกว่า

สำหรับบูลีนและค่าบูลีน - y

สำหรับ JS ไม่มีกฎทั่วไปของ AFAIK เป็นพิเศษเพราะมันเป็นเท็จแค่ไหนค่าได้รับการประเมิน

แต่ถ้าสิ่งที่สามารถช่วยคุณได้เกือบตลอดเวลาคือหรือตัวดำเนินการ ( ||):

// Instead of
var variable = this_one === true ? this_one : or_this_one;
// you can use
var variable = this_one || or_this_one;

คุณจะต้องระมัดระวังเป็นอย่างมากกับเรื่องนี้เพราะในตัวอย่างแรกของคุณindexOfสามารถกลับมา0และถ้าคุณประเมิน0 || -1ว่ามันจะกลับมา-1เพราะ0เป็นfalsyค่า


2
ขอบคุณ. ฉันเดาว่าตัวอย่างของฉันไม่ดีฉันแค่ยกตัวอย่างทั่วไปฮ่าฮ่าไม่ได้หาวิธีแก้ปัญหาที่แน่นอน ฉันเคยเผชิญกับ scnarios บางอย่างเช่นตัวอย่างที่ฉันต้องการใช้ ternary แต่สุดท้ายก็ทำซ้ำ :(
user1354934

1
ในตัวอย่างแรกทำอย่างไรเราจะตรวจสอบว่า3หรือ"y"ไม่ที่ดัชนี0ของsomeArray?
แขก 271314

ในMath.maxตัวอย่าง? indexOfส่งคืนดัชนีขององค์ประกอบและหากไม่พบองค์ประกอบจะส่งกลับ -1 ดังนั้นคุณมีโอกาสที่จะได้รับตัวเลขตั้งแต่ -1 ถึงความยาวของสตริงจากนั้นMath.maxคุณเพียงแค่กำหนดขอบเขตจาก 0 ถึงความยาวเพื่อลบโอกาส เพื่อคืนค่า -1,
Crisoforo Gaspar

@mitogh ตรรกะที่รหัสที่ OP สร้างปัญหาตัวอย่างทั่วไปแม้ว่าจะเป็น; โดยที่ 0 สามารถระบุดัชนี0ขององค์ประกอบที่ตรงกันภายในอาร์เรย์หรือ0ตั้งค่าที่Math.max(); หรือที่ตัวดำเนินการตามเงื่อนไขที่ OP. พิจารณาvar value = Math.max( ["y"].indexOf("y"), 0 ). คุณจะทราบได้อย่างไรว่ารายการใด0ถูกส่งคืน 0ส่งผ่านไปยังการMath.max()โทรหรือ0ดัชนีสะท้อนของ"y"ภายในอาร์เรย์?
แขก 271314

@ guest271314 คิดดี แต่ฉันคิดว่ามันขึ้นอยู่กับบริบทว่าเป็นปัญหาหรือไม่ บางทีมันไม่สำคัญว่า 0 มาจากไหนและสิ่งเดียวที่สำคัญคือมันไม่ใช่ -1 ตัวอย่าง: บางทีคุณอาจต้องเลือกรายการจากอาร์เรย์ คุณต้องการไอเท็มเฉพาะ (ใน OP หมายเลข 3) แต่ถ้ามันไม่ได้อยู่ในอาร์เรย์คุณยังต้องการไอเท็มและคุณก็สามารถกำหนดค่าเริ่มต้นให้กับไอเท็มแรกได้โดยสมมติว่าคุณรู้ว่าอาร์เรย์นั้นไม่ใช่ ' t ว่างเปล่า
Kev

27

ไม่จริงแค่ใช้ตัวแปรอื่น

ตัวอย่างของคุณแสดงถึงสิ่งต่างๆเช่นนี้

var x = predicate(f()) ? f() : default;

คุณกำลังทดสอบค่าที่คำนวณแล้วกำหนดค่านั้นให้กับตัวแปรหากผ่านเพรดิเคตบางส่วน วิธีหลีกเลี่ยงการคำนวณค่าที่คำนวณซ้ำนั้นชัดเจน: ใช้ตัวแปรเพื่อเก็บผลลัพธ์

var computed = f();
var x = predicate(computed) ? computed : default;

ฉันเข้าใจในสิ่งที่คุณหมายถึงดูเหมือนว่ามันน่าจะมีวิธีทำที่ดูสะอาดกว่านี้หน่อย แต่ฉันคิดว่านั่นเป็นวิธีที่ดีที่สุดในการทำสิ่งนี้ หากคุณทำรูปแบบนี้ซ้ำมากในโค้ดของคุณด้วยเหตุผลบางประการคุณอาจเขียนฟังก์ชันตัวช่วยเล็กน้อย:

var setif = (value, predicate, default) => predicate(value) ? value : default;
var x = setif(someArray.indexOf(3), x => x !== -1, 0)

18

แก้ไข: นี่คือข้อเสนอสำหรับNullary-coalescingใน JavaScript!


ใช้ ||

const result = a ? a : 'fallback value';

เทียบเท่ากับ

const result = a || 'fallback value';

ถ้าหล่อaเพื่อBooleanผลตอบแทนfalse, resultจะได้รับมอบหมายมิฉะนั้นค่าของ'fallback value'a


จะตระหนักถึงกรณีขอบa === 0ซึ่งจะปลดเปลื้องfalseและresultจะ (ถูก) 'fallback value'ใช้เวลา ใช้กลอุบายเช่นนี้โดยยอมรับความเสี่ยงของคุณเอง


ปล. ภาษาเช่น Swift มีตัวดำเนินการรวมศูนย์ ( ??) ซึ่งทำหน้าที่คล้ายกัน ตัวอย่างเช่นใน Swift คุณจะเขียนresult = a ?? "fallback value"ซึ่งค่อนข้างใกล้เคียงกับ JavaScriptconst result = a || 'fallback value';


3
PHP (> 7.0) และ C # ยังรองรับตัวดำเนินการเชื่อมต่อแบบ null น้ำตาลสังเคราะห์ แต่น่ารักแน่นอน
Hissvard

5
จะใช้ได้เฉพาะเมื่อฟังก์ชันส่งคืนค่าเท็จเมื่อล้มเหลว แต่indexOf()ไม่สามารถใช้ในรูปแบบนี้ได้
Barmar

1
ถูกต้อง แต่เขาไม่ได้ขอเฉพาะตัวอย่าง> "อีกครั้งไม่ได้ต้องการคำตอบสำหรับคำถามที่แน่นอนข้างต้นเป็นเพียงตัวอย่างของเวลาที่คุณอาจมีสิ่งต่างๆซ้ำ ๆ ในสถานศึกษา" <โปรดทราบว่าเขาค่อนข้างจะขอวิธีทั่วไปในการ แทนที่ ternary ที่ทำซ้ำ (ผลลัพธ์ = a? a: b) และการทำซ้ำ ternary เทียบเท่ากับ || (result = a || b)
Lyubomir

2
นั่นเป็นวิธีการ||ทำงานใน JavaScript จริงหรือ? ถ้าฉันเข้าใจคุณอย่างถูกต้องมันจะทำงานแตกต่างจากภาษาหลักอื่น ๆ อีกมากมาย (ฉันคิดว่าส่วนใหญ่เป็นภาษา C และลูกหลาน [C ++, Java ฯลฯ ]) แม้ว่าจะเป็นวิธีการ||ทำงานใน JavaScript จริงๆแต่ฉันก็ไม่แนะนำให้ใช้ เทคนิคเช่นนี้ซึ่งต้องการให้ผู้ดูแลต้องรู้นิสัยใจคอเป็นพิเศษเกี่ยวกับภาษา แม้ว่าเคล็ดลับนั้นจะเจ๋ง แต่ฉันก็คิดว่ามันเป็นการฝึกฝนที่ไม่ดี
Loduwijk

1
-1นอกจากนี้ยังสังเกตเห็นว่าคำถามคือการเปรียบเทียบค่า อีกครั้งฉันไม่สามารถพูดถึง JavaScript และนิสัยใจคอของมันได้ แต่โดยทั่วไปแล้ว-1จะเป็นค่าที่แท้จริงไม่ใช่ค่าเท็จดังนั้นคำตอบของคุณจะใช้ไม่ได้ในกรณีของคำถามและไม่ใช่กรณีทั่วไป แต่จะใช้ได้เฉพาะในกรณีเฉพาะ ( แต่ธรรมดาพอ) กรณีย่อย
Loduwijk

8

ใช้การปรับโครงสร้างตัวแปรแยก :

var index = someArray.indexOf(3);
var value = index !== -1 ? index : 0

มันจะดียิ่งขึ้นกับแทนconst varคุณสามารถทำการสกัดเพิ่มเติมได้:

const index = someArray.indexOf(3);
const condition = index !== -1;
const value = condition ? index : 0;

ในทางปฏิบัติใช้ชื่อที่มีความหมายมากกว่าindex, และconditionvalue

const threesIndex = someArray.indexOf(3);
const threeFound = threesIndex !== -1;
const threesIndexOrZero = threeFound ? threesIndex : 0;

"ตัวแปรสารสกัด" คืออะไร? เป็นคำที่กำหนดขึ้นหรือไม่?
Peter Mortensen

6

คุณอาจกำลังมองหาตัวดำเนินการประสาน โชคดีที่เราสามารถใช้ประโยชน์จากArrayต้นแบบเพื่อสร้าง:

Array.prototype.coalesce = function() {
    for (var i = 0; i < this.length; i++) {
        if (this[i] != false && this[i] != null) return this[i];
    }
}

[null, false, 0, 5, 'test'].coalesce(); // returns 5

สิ่งนี้สามารถสรุปได้มากขึ้นในกรณีของคุณโดยการเพิ่มพารามิเตอร์ให้กับฟังก์ชัน:

Array.prototype.coalesce = function(valid) {
    if (typeof valid !== 'function') {
        valid = function(a) {
            return a != false && a != null;
        }
    }

    for (var i = 0; i < this.length; i++) {
        if (valid(this[i])) return this[i];
    }
}

[null, false, 0, 5, 'test'].coalesce(); // still returns 5
[null, false, 0, 5, 'test'].coalesce(function(a){return a !== -1}); // returns null
[null, false, 0, 5, 'test'].coalesce(function(a){return a != null}); //returns false

การเพิ่มต้นแบบของอาร์เรย์มีความเสี่ยงเนื่องจากองค์ประกอบใหม่จะกลายเป็นดัชนีภายในทุกอาร์เรย์ ซึ่งหมายความว่าการทำซ้ำผ่านดัชนียังมีวิธีการใหม่: for (let x in ['b','c']) console.log(x);พิมพ์0, ,1 "coalesce"
Charlie Harding

@CharlieHarding True แต่โดยทั่วไปไม่แนะนำให้ใช้ตัวดำเนินการ for-in เมื่อวนลูปผ่านอาร์เรย์ ดูstackoverflow.com/a/4374244/1486100
Tyzoid

6

โดยส่วนตัวแล้วฉันชอบสองสายพันธุ์:

  1. บริสุทธิ์ถ้าเช่นที่ @slebetman แนะนำ

  2. ฟังก์ชันแยกซึ่งแทนที่ค่าที่ไม่ถูกต้องด้วยค่าเริ่มต้นเช่นในตัวอย่างนี้:

function maskNegative(v, def) {
  return v >= 0 ? v : def;
}

Array.prototype.indexOfOrDefault = function(v, def) {
  return maskNegative(this.indexOf(v), def);
}

var someArray = [1, 2];
console.log(someArray.indexOfOrDefault(2, 0)); // index is 1
console.log(someArray.indexOfOrDefault(3, 0)); // default 0 returned
console.log(someArray.indexOfOrDefault(3, 123)); // default 123 returned


1
+1 ตัวเลือก 2 เคารพในเจตนาของคำถามสามารถนำไปใช้กับภาษาอื่น ๆ ได้อย่างมีประสิทธิภาพนอกเหนือจากจาวาสคริปต์และส่งเสริมความเป็นโมดูลาร์
Devsman

5

ฉันชอบคำตอบของ @ slebetman ความคิดเห็นที่อยู่ข้างใต้แสดงความกังวลเกี่ยวกับตัวแปรที่อยู่ใน "สถานะกลาง" หากนี่เป็นปัญหาใหญ่สำหรับคุณฉันขอแนะนำให้ห่อหุ้มไว้ในฟังก์ชัน:

function get_value(arr) {
   var value = arr.indexOf(3);
   if (value === -1) {
     value = 0;
   }
   return value;
}

จากนั้นโทร

var value = get_value( someArray );

คุณสามารถทำฟังก์ชันทั่วไปได้มากขึ้นหากคุณใช้งานในที่อื่น ๆ แต่อย่าใช้วิศวกรมากเกินไปหากเป็นกรณีที่เฉพาะเจาะจงมาก

แต่พูดตามตรงฉันจะทำในฐานะ @slebetman เว้นแต่ฉันจะต้องใช้ซ้ำจากหลาย ๆ ที่


4

มีสองวิธีที่ฉันสามารถมองเห็นคำถามของคุณ: คุณต้องการลดความยาวของบรรทัดหรือคุณต้องการหลีกเลี่ยงการใช้ตัวแปรซ้ำใน ternary ประการแรกเป็นเรื่องเล็กน้อย (และผู้ใช้อื่น ๆ หลายคนได้โพสต์ตัวอย่าง):

var value = someArray.indexOf(3) !== -1 ? someArray.indexOf(3) : 0;

สามารถ (และควรได้รับการเรียกใช้ฟังก์ชัน) ให้สั้นลงดังนี้:

var value = someArray.indexOf(3);
value = value !== -1 ? value : 0;

หากคุณกำลังมองหาวิธีแก้ปัญหาทั่วไปที่ป้องกันการทำซ้ำของตัวแปรใน ternary เช่น:

var value = conditionalTest(foo) ? foo : bar;

ที่fooปรากฏเพียงครั้งเดียว การทิ้งโซลูชันของแบบฟอร์ม:

var cad = foo;
var value = conditionalTest(foo) ? cad : bar;

ตามเทคนิคที่ถูกต้อง แต่พลาดจุดนั้นคุณก็โชคไม่ดี มีตัวดำเนินการฟังก์ชันและวิธีการที่มีไวยากรณ์สั้น ๆ ที่คุณต้องการ แต่โครงสร้างดังกล่าวตามความหมายไม่ใช่ตัวดำเนินการที่เกี่ยวข้อง

ตัวอย่าง:

javascript ใช้||เพื่อส่งคืน RHS เมื่อ LHS คือfalsey:

var value = foo || bar; // equivalent to !foo ? bar : foo

1
คำถามถูกแท็กจาวาสคริปต์และไม่ได้กล่าวถึง C # แค่สงสัยว่าทำไมคุณถึงลงท้ายด้วยตัวอย่างเฉพาะของ C #
Loduwijk

ฉันพลาดแท็กจาวาสคริปต์ในคำถาม ลบ C #
asgallant

3

ใช้ฟังก์ชันตัวช่วย:

function translateValue(value, match, translated) {
   return value === match ? translated : value;
}

ตอนนี้โค้ดของคุณสามารถอ่านได้มากและไม่มีการทำซ้ำ

var value = translateValue(someArray.indexOf(3), -1, 0);

ลำดับชั้นของความกังวลในการเข้ารหัสคือ:

  1. ถูกต้อง (รวมถึงข้อกังวลด้านประสิทธิภาพที่แท้จริงหรือ SLA)
  2. ชัดเจน
  3. กระชับ
  4. เร็ว

คำตอบทั้งหมดในหน้านี้ดูเหมือนจะถูกต้อง แต่ฉันคิดว่าเวอร์ชันของฉันมีความชัดเจนสูงสุดซึ่งสำคัญกว่าความกระชับ หากคุณไม่นับฟังก์ชันตัวช่วยซึ่งสามารถนำกลับมาใช้ใหม่ได้ - ฟังก์ชันนี้จะรัดกุมที่สุดเช่นกัน คำแนะนำที่ค่อนข้างคล้ายกันในการใช้ฟังก์ชันตัวช่วยน่าเสียดายที่ใช้แลมบ์ดาซึ่งสำหรับฉันเพียงแค่ปิดบังสิ่งที่มันทำ ฟังก์ชั่นที่ง่ายกว่าโดยมีจุดประสงค์เดียวที่ไม่ใช้แลมด้าเพียงแค่ค่านิยมสำหรับฉันดีกว่ามาก

ปล. ถ้าคุณชอบไวยากรณ์ ES6:

const translateValue = (value, match, translated) => value === match ? translated : value;
let value = translateValue(someArray.indexOf(3), -1, 0); // or const

2
"เวอร์ชันของฉันมีความชัดเจนสูงสุด" - ฉันไม่เห็นด้วย ชื่อฟังก์ชันยาวเกินไปและการตั้งชื่อพารามิเตอร์อินพุตและเอาต์พุตไม่มีประโยชน์เลย
adelphus

คุณช่วยแนะนำชื่อที่ดีกว่านี้ได้ไหม ฉันยินดีที่จะให้ความบันเทิงแก่พวกเขา การร้องเรียนของคุณเป็นเรื่องเครื่องสำอางเท่านั้นดังนั้นเรามาแก้ไขเครื่องสำอางกันเถอะ ขวา? ไม่งั้นคุณก็แค่ปั่นจักรยาน
ErikE

ในบางกรณีฟังก์ชันตัวช่วยดังกล่าวอาจมีประโยชน์ ในกรณีนี้เมื่อแทนที่ตัวดำเนินการ ternary เฉพาะกรณีฟังก์ชันของคุณจะมีความชัดเจนน้อยลง ฉันจะจำไม่ได้ว่าฟังก์ชันของคุณทำอะไรและฉันจะต้องไปค้นหามันอีกครั้งทุกครั้งที่ฉันเจอมันและฉันจะไม่จำที่จะใช้มัน
Loduwijk

1
@Aaron นั่นเป็นการประเมินที่สมเหตุสมผลสำหรับกรณีการใช้งานเฉพาะ สำหรับสิ่งที่คุ้มค่าชื่อฟังก์ชั่นเดิมของฉันคือtranslateValueIfEqualสิ่งที่ฉันคิดว่าอธิบายได้มากกว่านี้ แต่ฉันเปลี่ยนมันหลังจากมีคนคิดว่ามันยาวเกินไป เช่นเดียวกับNzฟังก์ชันใน Access ถ้าคุณรู้คุณก็รู้และถ้าคุณไม่ทำคุณก็ทำไม่ได้ ใน IDE สมัยใหม่คุณสามารถกดปุ่มเพื่อข้ามไปยังคำจำกัดความได้ และทางเลือกจะเป็นตัวแปรกลาง ฉันไม่เห็นด้านล่างขนาดใหญ่ที่นี่จริงๆ
ErikE

1
นี่เป็นการแสดงให้เห็นว่าหากคุณถามคำถามเดียวกันกับวิศวกร 5 คนคุณจะได้รับคำตอบที่แตกต่างกัน 10 ข้อ
Loduwijk

2

ฉันคิดว่าตัว||ดำเนินการสามารถปรับให้เหมาะกับindexOf:

var value = ((someArray.indexOf(3) + 1) || 1) - 1;

ค่าที่ส่งคืนจะถูกเลื่อนขึ้นโดย 1 ทำให้ 0 จาก -1 ซึ่งเป็นเท็จดังนั้นจึงถูกแทนที่ด้วย 1 ที่สองจากนั้นจึงเลื่อนกลับ

อย่างไรก็ตามโปรดทราบว่าความสามารถในการอ่านดีกว่าการหลีกเลี่ยงการทำซ้ำ


2

นี่เป็นวิธีแก้ปัญหาง่ายๆโดยใช้bitwise NOTและค่าเริ่มต้น-1ซึ่งส่งผลให้เป็นศูนย์ในภายหลัง

index = ~(~array.indexOf(3) || -1);

มันทำงานโดยทั่วไปโดยใช้บิตสองเท่า NOT ซึ่งจะส่งคืนค่าเดิมหรือค่าเริ่มต้นซึ่งหลังจากใช้ bitwise แล้วจะไม่ส่งกลับศูนย์

มาดูตารางความจริงกัน:

 indexOf    ~indexOf   boolean    default     value      result         comment
---------  ---------  ---------  ---------  ---------  ---------  ------------------
      -1          0     falsy          -1         -1          0   take default value
       0         -1    truthy                     -1          0
       1         -2    truthy                     -2          1
       2         -3    truthy                     -3          2

0

คุณสามารถใช้การมอบหมายซ้ำ:

  • เริ่มต้นตัวแปรเป็นค่าเดียว
  • ใช้การทำให้เป็นอนุกรมของตัว&&ดำเนินการสำหรับการกำหนดใหม่เนื่องจากถ้าเงื่อนไขแรกเป็นเท็จนิพจน์ที่สองจะไม่ได้รับการประเมิน

เช่น

var value = someArray.indexOf(3);
value == -1 && (value=0);


3
@MinusFour ปริญญา ตัวแปรถูกทำซ้ำไม่ใช่การแสดงออก someArray.indexOfเพียงครั้งเดียว
vol7ron

valueคุณทำซ้ำ
MinusFour

3
@MinusFour ถูกต้อง แต่สิ่งนี้มีประโยชน์มากกว่าสำหรับนิพจน์ที่ใหญ่กว่าการทำซ้ำตัวแปรนั้นไม่มีนัยสำคัญเมื่อเทียบกับการบันทึกตัวดำเนินการ ฉันเดาว่า OP ใช้ไม่ได้-1และ0; มิฉะนั้นmax()จะเป็นตัวเลือกที่ดีที่สุด
vol7ron

2
ถูกต้อง ... แต่คำถามคือ ... "เขียนอย่างไรโดยไม่ให้ซ้ำตัวเอง"
MinusFour

4
นอกจากนี้ยังกล่าวว่าAgain, not seeking an answer to the exact question aboveซึ่งทำให้คำถามไปสู่การตีความ;)
vol7ron

0

ได้รับโค้ดตัวอย่างที่คำถามที่มันไม่ชัดเจนว่ามันจะได้รับการพิจารณาว่า3เป็นหรือไม่ได้ตั้งค่าที่ดัชนีของ0 การส่งคืนจากจะมีค่าในกรณีนี้เพื่อจุดประสงค์ในการยกเว้นการจับคู่ที่สันนิษฐานไว้ซึ่งอาจเป็นการจับคู่someArray-1.indexOf()

หาก3ไม่รวมอยู่ในอาร์เรย์-1จะถูกส่งกลับ เราสามารถเพิ่ม1ถึงผลของการ.indexOf()ที่จะประเมินผลเป็นfalseผลเป็น-1ที่ตามมาด้วยผู้ประกอบการและ|| OR 0เมื่อvalueมีการอ้างอิงลบที่จะได้รับดัชนีขององค์ประกอบของอาร์เรย์หรือ1-1

ซึ่งนำกลับไปเพียงแค่ใช้.indexOf()และตรวจสอบ-1ในifสภาพ หรือกำหนดvalueเป็นundefinedหลีกเลี่ยงความสับสนที่เป็นไปได้ผลจริงของสภาพการประเมินที่เกี่ยวข้องกับการอ้างอิงเดิม

var someArray = [1,2,3];
var value = someArray.indexOf(3) + 1 || 1;
console.log(value -= 1);

var someArray = [1,2,3];
var value = someArray.indexOf(4) + 1 || 1;
// how do we know that `4` is not at index `0`?
console.log(value -= 1);

var someArray = [1,2,3];
var value = someArray.indexOf(4) + 1 || void 0;
// we know for certain that `4` is not found in `someArray`
console.log(value, value = value || 0);


0

ternary ก็เหมือนกับ if-else ถ้าคุณไม่ต้องการส่วนอื่นทำไมไม่ใช้ if แทน ..

if ((value = someArray.indexOf(3)) < 0) value = 0;

0

สำหรับกรณีนี้คุณสามารถใช้การลัดวงจรกับตัว||ดำเนินการทางตรรกะ ในฐานะที่0เป็นที่ยอมรับว่า falsy คุณสามารถเพิ่ม1การจัดทำดัชนีของคุณจึงถ้าindex+1เป็นแล้วคุณจะได้รับทางด้านขวามือของตรรกะหรือเป็นผลของคุณมิฉะนั้นคุณจะได้รับของคุณ0 index+1เนื่องจากผลลัพธ์ที่คุณต้องการถูกหักล้างด้วย1คุณจึงสามารถลบออก1เพื่อให้ได้ดัชนีของคุณ:

const someArray = [1, 2, 3, 4];
const v = ((someArray.indexOf(3)+1) || 1)-1;
console.log(v);

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.