ฉันจะเก็บค่า“ ไม่รู้จัก” และ“ หายไป” ในตัวแปรได้อย่างไรในขณะที่ยังคงรักษาความแตกต่างระหว่าง“ ไม่ทราบ” และ“ หายไป”


57

พิจารณาคำถามนี้เป็น "วิชาการ" ฉันสงสัยเกี่ยวกับการหลีกเลี่ยง NULL เป็นครั้งคราวและนี่เป็นตัวอย่างที่ฉันไม่สามารถหาวิธีแก้ปัญหาที่น่าพอใจได้


สมมติว่าฉันเก็บค่าการวัดซึ่งบางครั้งการวัดนั้นเป็นไปไม่ได้ (หรือหายไป) ฉันต้องการเก็บค่า "ว่างเปล่า" ในตัวแปรในขณะที่หลีกเลี่ยงค่า NULL บางครั้งค่าอาจไม่เป็นที่รู้จัก ดังนั้นการมีการวัดสำหรับกรอบเวลาที่แน่นอนเคียวรีเกี่ยวกับการวัดภายในช่วงเวลานั้นอาจส่งคืนการตอบสนอง 3 ชนิด:

  • การวัดจริงในเวลานั้น (เช่นค่าตัวเลขใด ๆ รวมถึง0)
  • A "หายไป" / "ว่างเปล่า" ค่า (กล่าวคือเป็นวัดที่ได้กระทำและความคุ้มค่าเป็นที่รู้จักกันว่าเป็นที่ว่างเปล่าที่จุดนั้น)
  • ค่าที่ไม่รู้จัก (เช่นไม่มีการวัดที่จุดนั้นอาจว่างเปล่า แต่อาจเป็นค่าอื่นก็ได้)

ชี้แจงที่สำคัญ:

สมมติว่าคุณมีฟังก์ชันที่get_measurement()ส่งคืนหนึ่งใน "ว่างเปล่า", "ไม่ทราบ" และค่าประเภท "จำนวนเต็ม" การมีค่าตัวเลขแสดงถึงการดำเนินการบางอย่างที่สามารถทำได้ในค่าส่งคืน (การคูณการหาร ... ) แต่การใช้การดำเนินการดังกล่าวกับ NULLs จะทำให้แอปพลิเคชันเสียหายหากไม่ถูกจับ

ฉันต้องการที่จะสามารถเขียนรหัสหลีกเลี่ยงการตรวจสอบ NULL เช่น (pseudocode):

>>> value = get_measurement()  # returns `2`
>>> print(value * 2)
4

>>> value = get_measurement()  # returns `Empty()`
>>> print(value * 2)
Empty()

>>> value = get_measurement()  # returns `Unknown()`
>>> print(value * 2)
Unknown()

โปรดทราบว่าไม่มีprintคำสั่งใดที่ทำให้เกิดข้อยกเว้น (เนื่องจากไม่มี NULLs ถูกใช้) ดังนั้นค่าว่างและค่าที่ไม่รู้จักจะแพร่กระจายตามความจำเป็นและการตรวจสอบว่าค่าเป็น "ไม่ทราบ" หรือ "ว่างเปล่า" จริงอาจล่าช้าจนกว่าจะมีความจำเป็นจริง ๆ (เช่นการจัดเก็บ / การทำให้เป็นอนุกรม


หมายเหตุด้านข้าง: เหตุผลที่ฉันต้องการหลีกเลี่ยง NULL เป็นหลักช่วยพัฒนาสมอง ถ้าฉันต้องการทำสิ่งต่าง ๆ ฉันไม่ได้ต่อต้านการใช้ NULLs แต่ฉันพบว่าการหลีกเลี่ยงอาจทำให้โค้ดมีประสิทธิภาพมากขึ้นในบางกรณี


19
ทำไมคุณต้องการแยกความแตกต่าง "การวัดเสร็จแล้ว แต่ค่าว่างเปล่า" กับ "ไม่มีการวัด" ในความเป็นจริง "การวัดเสร็จแล้ว แต่มีค่าว่าง" หมายความว่าอย่างไร เซ็นเซอร์ไม่สามารถสร้างค่าที่ถูกต้องได้หรือไม่? ในกรณีนั้นแตกต่างจาก "ไม่ทราบ" อย่างไร คุณจะไม่สามารถย้อนเวลากลับไปและรับค่าที่ถูกต้องได้
DaveG

3
@DaveG สมมติว่าดึงจำนวน CPU ในเซิร์ฟเวอร์ หากเซิร์ฟเวอร์ถูกปิดหรือถูกทิ้งค่านั้นจะไม่มีอยู่จริง มันจะเป็นการวัดที่ไม่สมเหตุสมผล (อาจจะ "หายไป" / "ว่างเปล่า" ไม่ใช่คำที่ดีที่สุด) แต่คุณค่าคือ "รู้" ว่าไร้สาระ หากเซิร์ฟเวอร์มีอยู่ แต่กระบวนการดึงค่าขัดข้องการวัดจะใช้งานได้ แต่ล้มเหลวทำให้เกิดค่า "ไม่รู้จัก"
exhuma

2
@ exhuma ฉันจะอธิบายว่า "ไม่เกี่ยวข้อง" แล้ว
Vincent

6
จากการอยากรู้อยากเห็นคุณทำการวัดแบบไหนโดยที่ "ว่าง" ไม่เพียงเท่ากับศูนย์ของสเกลใดก็ตาม "ไม่ทราบ" / "หายไป" ฉันเห็นว่ามีประโยชน์เช่นถ้าเซ็นเซอร์ไม่ติดหรือถ้าเอาท์พุทของเซ็นเซอร์เป็นขยะด้วยเหตุผลใดเหตุผลหนึ่ง แต่ "ว่าง" ในทุกกรณีที่ฉันสามารถคิดได้อย่างต่อเนื่องมากขึ้น แสดงโดย0, []หรือ{}((เซนต์คิตส์และเนวิส 0, รายการว่างเปล่าและแผนที่ว่างตามลำดับ) นอกจากนี้ค่า "ขาดหายไป" / "ไม่ทราบ" นั้นเป็นสิ่งที่nullเกิดขึ้นจริง - มันแสดงให้เห็นว่าอาจมีวัตถุอยู่ที่นั่น แต่ไม่มี
Nic Hartley

7
ไม่ว่าวิธีแก้ปัญหาใดที่คุณใช้สำหรับสิ่งนี้ให้แน่ใจว่าถามตัวเองว่าปัญหาจากปัญหาที่คล้ายกันกับปัญหาที่ทำให้คุณต้องการกำจัด NULL ตั้งแต่แรก
เรย์

คำตอบ:


85

วิธีการทั่วไปในการทำสิ่งนี้อย่างน้อยก็ด้วยภาษาที่ใช้งานได้คือการใช้สหภาพที่มีการแบ่งแยก นี่คือค่าที่เป็นหนึ่งใน int ที่ถูกต้องค่าที่หมายถึง "ขาดหายไป" หรือค่าที่ระบุว่า "ไม่รู้จัก" ใน F # อาจมีลักษณะดังนี้:

type Measurement =
    | Reading of value : int
    | Missing
    | Unknown of value : RawData

Measurementค่าแล้วจะเป็นReadingมีค่า int หรือMissingหรือUnknownมีข้อมูลดิบเป็นvalue(ถ้าจำเป็น)

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


7
คุณสามารถทำประเภทผลรวมในภาษา OO แต่มีความยุติธรรมบิตของแผ่นหม้อไอน้ำที่จะทำให้พวกเขาทำงานstackoverflow.com/questions/3151702/...
JK

11
“ [ในภาษาที่ไม่สามารถใช้งานได้กับภาษา] รูปแบบนี้ไม่ค่อยมีประโยชน์สำหรับคุณมากนัก” - เป็นรูปแบบที่พบได้บ่อยใน OOP GOF มีรูปแบบของรูปแบบนี้ที่แตกต่างกันไปและภาษาต่างๆเช่น C ++ เสนอการสร้างแบบดั้งเดิมเพื่อเข้ารหัส
Konrad Rudolph

14
@jk ใช่พวกเขาไม่นับ (ดีฉันเดาว่าพวกเขาทำพวกเขาแย่มากในสถานการณ์นี้เนื่องจากขาดความปลอดภัย) ฉันหมายถึงstd::variant(และผู้บุกเบิกทางวิญญาณ)
Konrad Rudolph

2
@Ewan ไม่มันบอกว่า“ การวัดเป็นประเภทข้อมูลที่เป็น…หรือ…”
Konrad Rudolph

2
@DavidArno ถึงแม้จะไม่มี DUs ก็มีวิธีแก้ปัญหา "canonical" สำหรับ OOP ซึ่งจะต้องมี superclass ของค่าที่มี subclasses สำหรับค่าที่ถูกต้องและไม่ถูกต้อง แต่นั่นอาจจะไกลเกินไป (และในทางปฏิบัติดูเหมือนว่ารหัสส่วนใหญ่จะหลีกเลี่ยงความแตกต่างของคลาสย่อยในการสนับสนุนแฟล็กสำหรับสิ่งนี้ตามที่แสดงในคำตอบอื่น ๆ )
Konrad Rudolph

58

หากคุณยังไม่ทราบว่า monad คืออะไรวันนี้จะเป็นวันที่ดีสำหรับการเรียนรู้ ฉันมีการแนะนำอย่างนุ่มนวลสำหรับโปรแกรมเมอร์ OO ที่นี่:

https://ericlippert.com/2013/02/21/monads-part-one/

สถานการณ์ของคุณเป็นส่วนขยายเล็ก ๆ สำหรับ "บางที monad" ซึ่งรู้จักกันNullable<T>ใน C # และOptional<T>ในภาษาอื่น ๆ

สมมติว่าคุณมีรูปแบบนามธรรมเพื่อเป็นตัวแทนของ monad:

abstract class Measurement<T> { ... }

จากนั้นสามคลาสย่อย:

final class Unknown<T> : Measurement<T> { ... a singleton ...}
final class Empty<T> : Measurement<T> { ... a singleton ... }
final class Actual<T> : Measurement<T> { ... a wrapper around a T ...}

เราต้องการการนำ Bind ไปปฏิบัติ:

abstract class Measurement<T>
{ 
    public Measurement<R> Bind(Func<T, Measurement<R>> f)
  {
    if (this is Unknown<T>) return Unknown<R>.Singleton;
    if (this is Empty<T>) return Empty<R>.Singleton;
    if (this is Actual<T>) return f(((Actual<T>)this).Value);
    throw ...
  }

จากนี้คุณสามารถเขียน Bind เวอร์ชันที่เรียบง่ายนี้ได้:

public Measurement<R> Bind(Func<A, R> f) 
{
  return this.Bind(a => new Actual<R>(f(a));
}

และตอนนี้คุณทำเสร็จแล้ว คุณมีMeasurement<int>มือ คุณต้องการสองเท่า:

Measurement<int> m = whatever;
Measurement<int> doubled = m.Bind(a => a * 2);
Measurement<string> asString = m.Bind(a => a.ToString());

และทำตามตรรกะ; ถ้าmเป็นอย่างEmpty<int>นั้นasStringก็Empty<String>ยอดเยี่ยม

ในทำนองเดียวกันถ้าเรามี

Measurement<int> First()

และ

Measurement<double> Second(int i);

จากนั้นเราสามารถรวมการวัดสองแบบ:

Measurement<double> d = First().Bind(Second);

และอีกครั้งถ้าFirst()เป็นEmpty<int>แล้วdเป็นEmpty<double>และอื่น ๆ

ขั้นตอนที่สำคัญคือการได้รับการดำเนินการผูกที่ถูกต้อง คิดหนักเกี่ยวกับมัน


4
Monads (ขอบคุณ) ใช้งานง่ายกว่าที่จะเข้าใจ :)
Guran

11
@leftaroundabout: แม่นยำเพราะฉันไม่ต้องการแยกความแตกต่างของผม ในฐานะที่เป็นบันทึกย่อของโปสเตอร์ดั้งเดิมหลายคนขาดความมั่นใจเมื่อพูดถึงพระ ลักษณะเฉพาะของหมวดหมู่ทฤษฎีศัพท์แสง - ภาระของการดำเนินงานที่เรียบง่ายทำงานกับการพัฒนาความมั่นใจและความเข้าใจ
Eric Lippert

2
ดังนั้นคำแนะนำของคุณคือแทนที่Nullด้วยNullable+ บางรหัสสำเร็จรูป? :)
Eric Duminil

3
@Claude: คุณควรอ่านบทแนะนำของฉัน Monad เป็นประเภททั่วไปที่ปฏิบัติตามกฎบางอย่างและให้ความสามารถในการผูกสายการปฏิบัติการไว้ด้วยกันดังนั้นในกรณีนี้Measurement<T>คือประเภท monadic
Eric Lippert

5
@daboross: แม้ว่าฉันจะเห็นด้วยว่าพระที่เป็นรัฐเป็นวิธีที่ดีในการแนะนำพระ แต่ฉันไม่คิดว่าจะเป็นรัฐที่เป็นลักษณะของพระ ฉันคิดว่าความจริงที่ว่าคุณสามารถรวมกันเป็นลำดับฟังก์ชั่นเป็นสิ่งที่น่าสนใจ; สถานะเป็นเพียงรายละเอียดการนำไปปฏิบัติ
Eric Lippert

18

ฉันคิดว่าในกรณีนี้การเปลี่ยนแปลงในรูปแบบวัตถุ Null จะเป็นประโยชน์:

public class Measurement
{
    private int value;
    private bool isUnknown = false;
    private bool isMissing = false;

    private Measurement() { }
    public Measurement(int value) { this.value = value; }

    public int Value {
        get {
            if (!isUnknown && !isMissing)
            {
                return this.value;
            }
            throw new SomeException("...");
        }                   
    }

    public static readonly Measurement Unknown = new Measurement
    {
        isUnknown = true
    };

    public static readonly Measurement Missing = new Measurement
    {
        isMissing = true
    };
}

คุณสามารถเปลี่ยนมันเป็น struct, แทนที่ Equals / GetHashCode / ToString, เพิ่มการแปลงโดยนัยจากหรือไปint, และถ้าคุณต้องการพฤติกรรมที่เหมือน NaN คุณสามารถใช้ตัวดำเนินการทางคณิตศาสตร์ของคุณเองได้เช่น Measurement.Unknown * 2 == Measurement.Unknown.

ที่กล่าวว่า C # 's Nullable<int>การดำเนินการทั้งหมดที่มีข้อแม้เพียงอย่างเดียวว่าคุณจะไม่สามารถแยกความแตกต่างระหว่างประเภทที่แตกต่างกันของnulls ฉันไม่ใช่คน Java แต่ความเข้าใจของฉันก็คือ Java OptionalIntนั้นคล้ายกันและภาษาอื่น ๆ มีสิ่งอำนวยความสะดวกของตัวเองเพื่อเป็นตัวแทนOptionalประเภท


6
การนำไปใช้ที่พบบ่อยที่สุดที่ฉันเคยเห็นของรูปแบบนี้เกี่ยวข้องกับการสืบทอด อาจมีกรณีสำหรับสองคลาสย่อย: MissingMeasurement และ UnknownMeasurement พวกเขาสามารถใช้หรือแทนที่วิธีการในระดับการวัดผู้ปกครอง +1
Greg Burghardt

2
ไม่ใช่จุดของรูปแบบวัตถุ Nullที่คุณไม่ได้ล้มเหลวในค่าที่ไม่ถูกต้อง แต่ไม่ทำอะไรเลยใช่ไหม
Chris Wohlert

2
@ChrisWohlert ในกรณีนี้วัตถุไม่ได้จริงๆมีวิธีการใด ๆ ยกเว้นValueทะเยอทะยานซึ่งควรจะล้มเหลวอย่างที่คุณไม่สามารถแปลงกลับเป็นUnknown intหากการวัดมี a, say, SaveToDatabase()method แล้วการใช้งานที่ดีอาจจะไม่ทำธุรกรรมถ้าวัตถุปัจจุบันเป็นวัตถุว่างเปล่า
Maciej Stachowski

3
@MaciejStachowski ใช่ฉันไม่ได้บอกว่าไม่ควรทำอะไรเลยฉันกำลังบอกว่ารูปแบบของวัตถุ Nullนั้นไม่เหมาะสม วิธีการแก้ปัญหาของคุณอาจจะดี แต่ฉันจะไม่เรียกมันแบบ Null วัตถุ
Chris Wohlert

14

หากคุณต้องใช้จำนวนเต็มจริง ๆ มีวิธีแก้ปัญหาเดียวเท่านั้น ใช้ค่าที่เป็นไปได้บางอย่างเป็น 'หมายเลขมายากล' ซึ่งหมายถึง 'ขาด' และ 'ไม่รู้จัก'

เช่น 2,147,483,647 และ 2,147,483,646

หากคุณต้องการ int สำหรับการวัด 'ของจริง' จากนั้นสร้างโครงสร้างข้อมูลที่ซับซ้อนมากขึ้น

class Measurement {
    public bool IsEmpty;
    public bool IsKnown;
    public int Value {
        get {
            if(!IsEmpty && IsKnown) return _value;
            throw new Exception("NaN");
            }
        }
}

ชี้แจงที่สำคัญ:

คุณสามารถบรรลุความต้องการทางคณิตศาสตร์ได้โดยการบรรทุกผู้ปฏิบัติงานมากเกินไปสำหรับชั้นเรียน

public static Measurement operator+ (Measurement a, Measurement b) {
    if(a.IsEmpty) { return b; }
    ...etc
}

10
@KakturusOption<Option<Int>>
Bergi

5
@Bergi คุณไม่สามารถคิดว่ามันเป็นที่ยอมรับจากระยะไกล ..
BlueRaja - Danny Pflughoeft

8
@ BlueRaja-DannyPflughoeft จริงๆแล้วมันเหมาะกับคำอธิบาย OPs ค่อนข้างดีซึ่งมีโครงสร้างซ้อนกันเช่นกัน เพื่อให้เป็นที่ยอมรับเราขอแนะนำนามแฝงประเภทที่เหมาะสม (หรือ "newtype") แน่นอน - แต่type Measurement = Option<Int>สำหรับผลลัพธ์ที่เป็นจำนวนเต็มหรือการอ่านว่างเปล่าก็โอเคและOption<Measurement>สำหรับการวัดที่อาจถูกถ่ายหรือไม่ .
Bergi

7
@arp "จำนวนเต็มใกล้น่าน" คุณสามารถอธิบายสิ่งที่คุณหมายถึงโดยที่? ดูเหมือนว่าค่อนข้างใช้งานง่ายเพื่อบอกว่าตัวเลขคือ "ใกล้" แนวคิดของสิ่งที่ไม่ใช่ตัวเลข
Nic Hartley

3
@Nic Hartley ในระบบของเรากลุ่มของสิ่งที่ "เป็นธรรมชาติ" นั้นเป็นจำนวนเต็มต่ำสุดที่เป็นไปได้ซึ่งสงวนไว้เป็น NaN เราใช้พื้นที่นั้นเพื่อเข้ารหัสเหตุผลหลายประการว่าทำไมไบต์เหล่านั้นจึงแสดงข้อมูลอื่นนอกเหนือจากข้อมูลที่ถูกกฎหมาย (เป็นทศวรรษที่ผ่านมาและฉันอาจทำให้รายละเอียดบางอย่างเลือนลาง แต่มีบิตจำนวนหนึ่งที่คุณสามารถใส่ค่าจำนวนเต็มเพื่อทำให้โยน NaN ถ้าคุณพยายามทำคณิตศาสตร์ด้วย
arp

11

หากตัวแปรของคุณจะมีหมายเลขจุดลอย IEEE754 (ลอยมาตรฐานจำนวนจุดซึ่งสนับสนุนโดยโปรเซสเซอร์ที่ทันสมัยที่สุดและภาษา) มีหลังของคุณ: มันเป็นคุณลักษณะที่รู้จักกันน้อย แต่มาตรฐานกำหนดไม่หนึ่ง แต่ทั้งครอบครัวของค่า NaN (ไม่ใช่ตัวเลข) ซึ่งสามารถใช้สำหรับความหมายที่กำหนดโดยแอปพลิเคชันโดยพลการ ตัวอย่างเช่นในการลอยที่มีความแม่นยำเดียวคุณมี 22 บิตอิสระที่คุณสามารถใช้เพื่อแยกความแตกต่างระหว่างค่าที่ไม่ถูกต้อง 2 ^ {22} ประเภท

โดยปกติอินเตอร์เฟสการเขียนโปรแกรมจะเปิดเผยเพียงหนึ่งในนั้น (เช่น Numpy's nan); ฉันไม่รู้ว่ามีวิธีในตัวที่จะสร้างส่วนอื่นนอกเหนือจากการจัดการบิตอย่างชัดเจนหรือไม่ แต่เป็นเพียงเรื่องของการเขียนกิจวัตรระดับล่างสองสามอย่าง (คุณจะต้องมีหนึ่งคนที่จะบอกพวกเขาแยกจากกันเพราะจากการออกแบบa == bจะส่งกลับเท็จเสมอเมื่อหนึ่งในนั้นคือ NaN)

การใช้พวกมันนั้นดีกว่าการสร้าง "หมายเลขเวทมนต์" ของคุณเองเพื่อส่งสัญญาณข้อมูลที่ไม่ถูกต้องเพราะมันแพร่กระจายอย่างถูกต้องและส่งสัญญาณที่ไม่ถูกต้อง: ตัวอย่างเช่นคุณไม่เสี่ยงต่อการยิงตัวเองหากคุณใช้average()ฟังก์ชั่น คุณค่าพิเศษของคุณ

ความเสี่ยงเพียงอย่างเดียวคือไลบรารีไม่สนับสนุนอย่างถูกต้องเนื่องจากเป็นคุณลักษณะที่คลุมเครือ: ตัวอย่างเช่นไลบรารี่ที่เป็นอนุกรมอาจ 'ทำให้แบน' พวกมันทั้งหมดเหมือนกันnan(ซึ่งมีลักษณะเทียบเท่ากับเพื่อวัตถุประสงค์ส่วนใหญ่)


6

ต่อไปนี้ในคำตอบที่เดวิดอาร์โนของคุณสามารถทำอะไรเช่นสหภาพการเลือกปฏิบัติใน OOP และในรูปแบบวัตถุทำงานเช่นที่ afforded โดย Scala โดย Java 8 ชนิดทำงานหรือ Java ห้องสมุด FP เช่นVavrหรือความทรงจำมันให้ความรู้สึกที่เป็นธรรม เป็นธรรมชาติที่จะเขียนสิ่งที่ชอบ:

var value = Measurement.of(2);
out.println(value.map(x -> x * 2));

var empty = Measurement.empty();
out.println(empty.map(x -> x * 2));

var unknown = Measurement.unknown();
out.println(unknown.map(x -> x * 2));

การพิมพ์

Value(4)
Empty()
Unknown()

( การนำไปใช้อย่างเต็มรูปแบบเป็นส่วนสำคัญ )

ภาษาหรือไลบรารี FP มีเครื่องมืออื่น ๆ เช่นTry(aka Maybe) (วัตถุที่มีทั้งค่าหรือข้อผิดพลาด) และEither(วัตถุที่มีค่าความสำเร็จหรือค่าความล้มเหลว) ที่สามารถใช้ที่นี่


2

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

เพียงแค่เริ่มต้นด้วย "รสชาติที่สอง" เป็นโมฆะไม่ได้ให้ชุดของกระบวนการข้อมูลที่เพียงพอสำหรับการรับชุดพฤติกรรมที่เหมาะสม

หากคุณพึ่งพาสมมติฐานตามบริบทแทนแหล่งที่มาของพฤติกรรมที่ไม่ดีที่เกิดจากโค้ดดาวน์สตรีมฉันจะเรียกสถาปัตยกรรมที่ไม่ดีนั้น

หากคุณรู้จักพอที่จะแยกแยะระหว่างเหตุผลของความล้มเหลวและความล้มเหลวโดยไม่มีเหตุผลที่ทราบและข้อมูลนั้นจะแจ้งพฤติกรรมในอนาคตคุณควรจะสื่อสารความรู้นั้นดาวน์สตรีมหรือจัดการแบบอินไลน์

รูปแบบบางอย่างสำหรับจัดการสิ่งนี้:

  • ประเภทผลรวม
  • สหภาพที่ถูกเลือกปฏิบัติ
  • วัตถุหรือ structs ที่มีค่า enum แสดงผลลัพธ์ของการดำเนินการและเขตข้อมูลสำหรับผลลัพธ์
  • สายเวทหรือหมายเลขเวทย์มนตร์ที่ไม่สามารถทำได้ผ่านการทำงานปกติ
  • ข้อยกเว้นในภาษาที่มีการใช้งานนี้เป็นสำนวน
  • ตระหนักว่าไม่มีค่าใด ๆ ในการแยกความแตกต่างระหว่างสองสถานการณ์นี้และเพียงแค่ใช้ null

2

หากฉันเกี่ยวข้องกับ "ทำให้บางสิ่งบางอย่างเสร็จสิ้น" แทนที่จะเป็นวิธีแก้ปัญหาที่หรูหราการแฮ็คที่รวดเร็วและสกปรกก็คือการใช้สตริง "ไม่ทราบ", "หายไป" และ 'การแทนสตริงของค่าตัวเลขของฉัน' ซึ่งจะเป็น แปลงจากสตริงและใช้ตามต้องการ ใช้งานได้เร็วกว่าการเขียนนี้และอย่างน้อยในบางสถานการณ์ก็เพียงพอแล้ว (ตอนนี้ฉันกำลังรวมกลุ่มการเดิมพันกับจำนวน downvotes ... )


โหวตขึ้นเพื่อกล่าวถึง "การทำบางสิ่งให้สำเร็จ"
บาร์บีคิว

4
บางคนอาจทราบว่าสิ่งนี้ได้รับความเดือดร้อนจากปัญหาส่วนใหญ่เช่นเดียวกับการใช้ NULL นั่นคือมันเปลี่ยนจากการต้องการการตรวจสอบ NULL ไปเป็นการตรวจสอบ "ไม่ทราบ" และ "หายไป" แต่ทำให้เวลาทำงานล้มเหลวสำหรับความโชคดี โชคร้ายที่เป็นตัวบ่งชี้เดียวที่คุณลืมเช็ค แม้ว่าการตรวจสอบ NULL ที่หายไปจะมีข้อดีที่ linters อาจตรวจจับได้ แต่สิ่งนี้จะสูญเสียสิ่งนั้นไป มันจะเพิ่มความแตกต่างระหว่าง "ไม่ทราบ" และ "หายไป" ดังนั้นจึงเป็นโมฆะที่นั่น ...
8bittree

2

ส่วนสำคัญหากคำถามดูเหมือนจะเป็น "ฉันจะคืนข้อมูลสองชิ้นที่ไม่เกี่ยวข้องจากวิธีการที่ส่งกลับ int เดียวได้หรือไม่ฉันไม่ต้องการตรวจสอบค่าตอบแทนของฉันและ null จะไม่ดีอย่าใช้พวกเขา"

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

ตอนแรกดูเหมือนว่ามันจะเป็นกรณีที่ดีสำหรับการโยนข้อยกเว้น

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

และนี่คือระบบเท่านั้นที่อนุญาตให้คุณคืนค่า int ที่ถูกต้องและรับประกันได้ว่าตัวดำเนินการ int และวิธีการที่ใช้ ints ทุกตัวสามารถรับค่าตอบแทนของวิธีนี้ได้โดยไม่จำเป็นต้องตรวจสอบค่าที่ไม่ถูกต้องเช่น null หรือค่ามายากล

แต่ข้อยกเว้นเป็นเพียงวิธีแก้ปัญหาที่ถูกต้องเท่านั้นหากตามความหมายของชื่อนี่เป็นกรณีพิเศษไม่ใช่ธุรกิจปกติ

และลอง / จับและจัดการเป็นเพียงมากสำเร็จรูปเป็นเช็คโมฆะซึ่งเป็นสิ่งที่คัดค้านไปในสถานที่แรก

และหากผู้โทรไม่มีการลอง / จับผู้โทรจะต้องดำเนินการต่อไปเรื่อย ๆ


การผ่านครั้งที่สองที่ไร้เดียงสาคือการพูดว่า "เป็นการวัดการวัดระยะทางเชิงลบนั้นไม่น่าเป็นไปได้" ดังนั้นสำหรับการวัดค่า Y คุณสามารถมี const สำหรับ

  • -1 = ไม่รู้จัก
  • -2 = วัดไม่ได้
  • -3 = ปฏิเสธที่จะตอบ
  • -4 = รู้จัก แต่เป็นความลับ
  • -5 = แตกต่างกันไปขึ้นอยู่กับระยะดวงจันทร์ดูตาราง 5a
  • -6 = สี่มิติ, การวัดที่กำหนดในหัวเรื่อง,
  • -7 = ข้อผิดพลาดในการอ่านระบบไฟล์
  • -8 = สงวนไว้สำหรับใช้ในอนาคต
  • -9 = สี่เหลี่ยมจัตุรัส / ลูกบาศก์ดังนั้น Y เท่ากับ X
  • -10 = เป็นหน้าจอมอนิเตอร์ดังนั้นจึงไม่ใช้การวัด X, Y: ใช้ X เป็นเส้นทแยงมุมจอภาพ
  • -11 = เขียนการวัดลงที่ด้านหลังของใบเสร็จรับเงินและมันถูกฟอกเป็นความไม่ถูกต้อง แต่ฉันคิดว่ามันเป็น 5 หรือ 17
  • -12 = ... คุณได้ความคิด

นี่คือวิธีที่มันทำในระบบ C รุ่นเก่าจำนวนมากและแม้แต่ในระบบที่ทันสมัยซึ่งมีข้อ จำกัด อย่างแท้จริงถึง int และคุณไม่สามารถห่อมันไว้กับ struct หรือ monad ของบางประเภท

หากการวัดสามารถเป็นลบได้คุณเพียงแค่ทำให้ประเภทข้อมูลของคุณมีขนาดใหญ่ขึ้น (เช่น int ยาว) และมีค่าเวทมนตร์สูงกว่าช่วงของ int และเริ่มต้นด้วยค่าบางอย่างที่จะปรากฏอย่างชัดเจนในดีบักเกอร์

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


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

ในกรณีนั้นมันดูดีสำหรับโครงสร้างที่ผ่าน int และเหตุผล อีกครั้งเหตุผลนี้อาจจะเป็น const เช่นข้างต้น แต่แทนที่จะถือทั้งสองใน int เดียวกันคุณเก็บไว้เป็นส่วนต่าง ๆ ของโครงสร้าง เริ่มแรกเรามีกฎว่าหากมีการตั้งค่าเหตุผลจะไม่มีการตั้งค่า int แต่เราไม่ได้ผูกติดอยู่กับกฎนี้อีกต่อไป เราสามารถให้เหตุผลสำหรับตัวเลขที่ถูกต้องเช่นกันหากต้องการ

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

ที่นี่คุณจำเป็นต้องตรวจสอบเหตุผลของคุณหลัง "ไม่ใช้ค่าว่าง"

เช่นเดียวกับข้อยกเว้น null หมายถึงสถานะพิเศษ

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

ดังนั้นทุกครั้งที่คุณเรียกใช้เมธอดนี้คุณจะต้องทำการตรวจสอบค่าส่งคืน แต่คุณต้องจัดการกับค่าที่ไม่ถูกต้องไม่ว่าจะอยู่ในแบนด์หรือแบนด์ลอง / จับตรวจสอบโครงสร้างสำหรับองค์ประกอบ "เหตุผล" ตรวจสอบอิน สำหรับหมายเลขมายากลหรือตรวจสอบ int สำหรับ null ...

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

... จากนั้นให้ผู้ให้บริการรายอื่นเกินพิกัดในแอปพลิเคชันของคุณที่อาจนำไปใช้กับข้อมูลนี้

... และเกินวิธีการทั้งหมดที่ใช้ ints

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

ดังนั้นหลักฐานดั้งเดิมจึงเป็นเท็จในหลายวิธี:

  1. หากคุณมีค่าที่ไม่ถูกต้องคุณจะไม่สามารถหลีกเลี่ยงการตรวจสอบค่าที่ไม่ถูกต้องได้ทุกเมื่อในรหัสที่คุณจัดการค่า
  2. หากคุณส่งคืนสิ่งอื่นนอกเหนือจาก int คุณจะไม่ส่งคืนค่า int ดังนั้นคุณจะไม่สามารถปฏิบัติได้เหมือน int ผู้ประกอบการมากไปช่วยให้คุณแกล้งแต่นั่นเป็นเพียงการแกล้ง
  3. int ที่มีตัวเลขเวทย์มนตร์ (รวมถึง NULL, NAN, Inf ... ) ไม่ได้เป็น int จริงๆอีกต่อไปมันเป็นโครงสร้างของคนยากจน
  4. การหลีกเลี่ยงค่า Null จะไม่ทำให้รหัสมีเสถียรภาพมากขึ้น แต่จะซ่อนปัญหากับ ints หรือย้ายไปไว้ในโครงสร้างการจัดการข้อยกเว้นที่ซับซ้อน

1

ฉันไม่เข้าใจหลักฐานของคำถามของคุณ แต่นี่คือคำตอบที่มีคุณค่า สำหรับ Missing หรือ Empty คุณสามารถทำได้math.nan(ไม่ใช่ตัวเลข) คุณสามารถดำเนินการใด ๆ ทางคณิตศาสตร์ในและมันจะยังคงอยู่math.nanmath.nan

คุณสามารถใช้None(Python null) สำหรับค่าที่ไม่รู้จัก คุณไม่ควรจัดการค่าที่ไม่รู้จักอย่างไรก็ตามและบางภาษา (Python ไม่ใช่หนึ่งในนั้น) มีโอเปอเรเตอร์พิเศษเป็นโมฆะดังนั้นการดำเนินการจะดำเนินการเฉพาะในกรณีที่ค่าไม่เป็นโมฆะมิฉะนั้นค่าจะเป็นโมฆะ

ภาษาอื่นมีคำสั่งป้องกัน (เช่น Swift หรือ Ruby) และ Ruby มีการส่งคืนก่อนกำหนดแบบมีเงื่อนไข

ฉันเห็นสิ่งนี้ถูกแก้ไขใน Python ด้วยวิธีที่ต่างกัน:

  • ด้วยโครงสร้างข้อมูล wrapper เนื่องจากข้อมูลตัวเลขมักจะเกี่ยวกับเอนทิตีและมีเวลาในการวัด wrapper สามารถแทนที่วิธีเวทย์มนตร์อย่างเช่น__mult__ไม่มีการยกข้อยกเว้นเมื่อค่าที่ไม่รู้จักหรือค่าที่หายไปของคุณเกิดขึ้น คนอ้วนและหมีแพนด้าอาจมีความสามารถเช่นนั้น
  • ด้วยค่าแมวมอง (เช่นคุณUnknownหรือ -1 / -2) และคำสั่ง if
  • ด้วยธงบูลีนแยก
  • ด้วยโครงสร้างข้อมูลขี้เกียจ - ฟังก์ชั่นของคุณจะทำการดำเนินการบางอย่างกับโครงสร้างจากนั้นจะส่งคืนฟังก์ชันภายนอกสุดที่ต้องการผลลัพธ์ที่แท้จริงจะประเมินโครงสร้างข้อมูลขี้เกียจ
  • ด้วยขั้นตอนการทำงานที่ขี้เกียจคล้ายกับก่อนหน้านี้ แต่สามารถใช้กับชุดข้อมูลหรือฐานข้อมูล

1

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

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

โซลูชันที่ 1: อย่าหลีกเลี่ยงการตรวจสอบค่าว่าง

Missingสามารถแทนได้ตามที่math.nan
Unknownสามารถแทนได้None

หากคุณมีมากกว่าหนึ่งค่าคุณสามารถfilter()ใช้การดำเนินการกับค่าที่ไม่ใช่UnknownหรือMissingหรือค่าใด ๆ ที่คุณต้องการละเว้นสำหรับฟังก์ชัน

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


โซลูชันที่ 2: ใช้มัณฑนากรที่จับข้อยกเว้น

ในกรณีนี้Missingสามารถเพิ่มMissingExceptionและUnknownเพิ่มได้UnknownExceptionเมื่อมีการดำเนินการกับมัน

@suppressUnknown(value=Unknown) # if an UnknownException is raised, return this value instead
@suppressMissing(value=Missing)
def sigmoid(value):
    ...

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

เมื่อคุณเรียกใช้ฟังก์ชันไม่คาดหวังว่า Missing จะได้ Missing ฟังก์ชันนั้นจะเพิ่มขึ้นทันทีโดยแสดงให้คุณเห็นว่าเกิดข้อผิดพลาดขึ้นที่ใดแทนที่จะเป็นความล้มเหลวอย่างเงียบ ๆ เช่นเดียวกับที่ไม่รู้จัก

sigmoidยังคงสามารถโทรsinถึงแม้ว่ามันจะไม่ได้คาดหวังMissingหรือUnknownเพราะsigmoidมัณฑนากรของจะจับข้อยกเว้น


1
สงสัยว่าสิ่งที่จุดของการโพสต์สองคำตอบสำหรับคำถามเดียวกัน (นี่คือคำตอบก่อนหน้าของคุณมีอะไรผิดปกติกับมัน?)
ริ้น

@gnat คำตอบนี้ให้เหตุผลว่าทำไมไม่ควรทำในแบบที่ผู้เขียนแสดงและฉันไม่ต้องการให้ยุ่งยากในการรวมสองคำตอบกับความคิดที่แตกต่าง - มันง่ายกว่าที่จะเขียนสองคำตอบที่สามารถอ่านได้อย่างอิสระ . ฉันไม่เข้าใจว่าทำไมคุณห่วงใยคนอื่นด้วยเหตุผลที่ไม่เป็นอันตราย
noɥʇʎԀʎzɐɹƆ

0

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

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

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


0

คำตอบที่ได้นั้นดี แต่ก็ยังไม่สะท้อนความสัมพันธ์แบบลำดับชั้นระหว่างค่าว่างเปล่าและไม่ทราบ

  • สูงสุดมาที่ไม่รู้จัก
  • จากนั้นก่อนที่จะใช้ค่าแรกที่ว่างเปล่าจะต้องมีการชี้แจง
  • Last มาพร้อมค่าที่จะคำนวณด้วย

น่าเกลียด (สำหรับความล้มเหลวที่เป็นนามธรรม) แต่การดำเนินการอย่างเต็มที่จะเป็น (ใน Java):

Optional<Optional<Integer>> unknowableValue;

unknowableValue.ifPresent(emptiableValue -> ...);
Optional<Integer> emptiableValue = unknowableValue.orElse(Optional.empty());

emptiableValue.ifPresent(value -> ...);
int value = emptiableValue.orElse(0);

ภาษาที่ใช้งานได้ด้วยระบบประเภทที่ดีจะดีกว่า

ในความเป็นจริง:ว่าง / ที่ขาดหายไปและไม่รู้จัก *ค่าที่ไม่ใช่ดูเหมือนค่อนข้างเป็นส่วนหนึ่งของกระบวนการบางรัฐบางผลิตท่อ เช่นเดียวกับ Excel สเปรดชีตเซลล์ที่มีสูตรอ้างอิงเซลล์อื่น ๆ มีใครจะนึกถึงการเก็บลูกแกะตามบริบท การเปลี่ยนเซลล์จะทำการประเมินเซลล์ที่ต้องพึ่งพาซ้ำทั้งหมด

ในกรณีนั้นค่า int จะได้รับจากผู้จัดหาสินค้า ค่าว่างจะให้ผู้จัดหา int ส่งข้อยกเว้นที่ว่างเปล่าหรือประเมินว่าว่างเปล่า (ซ้ำไปซ้ำ) สูตรหลักของคุณจะเชื่อมต่อค่าทั้งหมดและอาจส่งคืนค่าว่าง (ค่า / ข้อยกเว้น) ค่าที่ไม่รู้จักจะปิดใช้งานการประเมินผลโดยการโยนข้อยกเว้น

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

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


0

ใช่แนวคิดของNA ประเภทต่าง ๆมีอยู่ในบางภาษา ยิ่งกว่านั้นในสถิติที่มีความหมายมากกว่า (กล่าวคือความแตกต่างอย่างมากระหว่างMissing-At-Random, Missing-Complete-At-Random, Missing-Not-At-Random )

  • หากเราวัดความยาวของวิดเจ็ตเท่านั้นก็ไม่สำคัญที่จะแยกความแตกต่างระหว่าง 'ความล้มเหลวของเซ็นเซอร์' หรือ 'ไฟตัด' หรือ 'ความล้มเหลวของเครือข่าย' (แม้ว่า 'ตัวเลขล้น' จะสื่อข้อมูล)

  • แต่ในเช่นการทำเหมืองข้อมูลหรือการสำรวจการถามผู้ตอบแบบสอบถามเช่นรายได้หรือสถานะเอชไอวีผลลัพธ์ของ 'ไม่ทราบ' นั้นแตกต่างจาก 'ปฏิเสธคำตอบ' และคุณสามารถเห็นได้ว่าสมมติฐานก่อนหน้าของเรา จะแตกต่างจากอดีต ดังนั้นภาษาอย่าง SAS รองรับ NA ประเภทต่าง ๆ ; ภาษา R ไม่เพียง แต่ผู้ใช้มักจะต้องแฮ็คสิ่งนั้น NAs ที่จุดต่าง ๆ ในไปป์ไลน์สามารถใช้เพื่อแสดงถึงสิ่งที่แตกต่างกันมาก

  • นอกจากนี้ยังมีกรณีที่เรามีตัวแปร NA หลายรายการสำหรับรายการเดียว ("การใส่หลายรายการ") ตัวอย่าง: หากฉันไม่ทราบอายุรหัสไปรษณีย์ระดับการศึกษาหรือรายได้ของบุคคลใดบุคคลหนึ่งจะเป็นการยากที่จะกำหนดรายได้

สำหรับวิธีที่คุณแสดง NA ประเภทต่าง ๆ ในภาษาที่ใช้งานทั่วไปที่ไม่สนับสนุนพวกเขาโดยทั่วไปคนจะแฮ็คสิ่งต่างๆเช่น floating-point-NaN (ต้องแปลงจำนวนเต็ม), enums หรือ sentinels (เช่น 999 หรือ -1000) สำหรับจำนวนเต็มหรือ ค่าเด็ดขาด ปกติจะไม่มีคำตอบที่สะอาดมากขอโทษ


0

R มีการสนับสนุนมูลค่าที่ขาดหายไปในตัว https://medium.com/coinmonks/dealing-with-missing-data-using-r-3ae428da2d17

แก้ไข: เนื่องจากฉันถูกลงคะแนนฉันจะอธิบายเล็กน้อย

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

อย่างไรก็ตามคุณสามารถทำเครื่องหมายว่าคุณขาดข้อมูลเช่นจุดหรือ "หายไป" หรืออะไรก็ได้ ใน R คุณสามารถกำหนดสิ่งที่คุณหมายถึงการขาดหายไป คุณไม่จำเป็นต้องแปลงพวกเขา

NAวิธีปกติในการกำหนดค่าที่หายไปคือการทำเครื่องหมายว่า

x <- c(1, 2, NA, 4, "")

จากนั้นคุณสามารถดูว่ามีค่าใดหายไป;

is.na(x)

แล้วผลจะเป็น;

FALSE FALSE  TRUE FALSE FALSE

อย่างที่คุณเห็นว่า""ไม่ขาดหาย คุณสามารถคุกคาม""ที่ไม่รู้จัก และNAจะหายไป


@Hulk ภาษาอื่น ๆ ที่ใช้ในการทำงานรองรับค่าที่ขาดหายไปคืออะไร? แม้ว่าพวกเขาจะสนับสนุนค่าที่ขาดหายไปฉันแน่ใจว่าคุณไม่สามารถเติมพวกเขาด้วยวิธีการทางสถิติในรหัสบรรทัดเดียว
ilhan

-1

มีเหตุผลที่ฟังก์ชั่นการใช้งานของ*ผู้ปฏิบัติงานไม่สามารถเปลี่ยนแปลงได้แทนหรือไม่?

คำตอบส่วนใหญ่เกี่ยวข้องกับค่าการค้นหาของบางประเภท แต่อาจง่ายกว่าในการแก้ไขตัวดำเนินการทางคณิตศาสตร์ในกรณีนี้

จากนั้นคุณจะสามารถมีempty()/ unknown()หน้าที่คล้ายกันในโครงการทั้งหมดของคุณ


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