「不明」と「欠損」の違いを保持したまま、変数に「不明」と「欠損」の値を保存する方法を教えてください。


57

これを「アカデミック」な質問と考えてください。私は時々NULLを避けることについて疑問に思っていましたが、これは満足のいく解決策を思い付かない例です。


測定が不可能(または欠落)であることがわかっている場合に測定値を保存するとします。NULLを避けながら、変数にその「空の」値を格納したいと思います。また、値が不明な場合もあります。そのため、特定の時間枠の測定値がある場合、その期間内の測定値に関するクエリは3種類の応答を返す可能性があります。

  • その時点での実際の測定値(たとえば、を含む数値0
  • 「欠落」/「空」の値(つまり、測定が行われ、その時点で値が空であることがわかっている)。
  • 不明な値(つまり、その時点で測定は行われていません。空になることもありますが、他の値になることもあります)。

重要な説明:

get_measurement()「空」、「不明」、および「整数」型の値のいずれかを返す関数があると仮定します。数値があるということは、戻り値(乗算、除算など)で特定の操作を実行できることを意味しますが、そのような操作をNULLで使用すると、キャッチされないとアプリケーションがクラッシュします。

NULLチェックを回避して、コードを記述できるようにしたいと思います。たとえば(擬似コード):

>>> 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()

printNULLが使用されていないため、どのステートメントも例外を引き起こしていません。したがって、空の値と不明な値は必要に応じて伝播し、値が実際に「不明」または「空」であるかどうかのチェックは、本当に必要になるまで遅らせることができます(値の保存/シリアル化など)。


サイドノート:NULLを避けたい理由は、主に頭の体操です。何かをやりたい場合、NULLを使用することに反対しませんが、それらを回避することでコードがより堅牢になる場合があることがわかりました。


19
「測定済みだが空の値」と「測定なし」を区別したいのはなぜですか?実際、「測定は完了したが空の値」とはどういう意味ですか?センサーは有効な値を生成できませんでしたか?その場合、それは「不明」とどう違うのですか?時間をさかのぼって正しい値を取得することはできません。
-DaveG

3
@DaveGサーバー内のCPUの数を取得すると仮定します。サーバーの電源が切れているか、廃棄されている場合、その値は存在しません。意味をなさない測定値になります(「欠落」/「空」は最良の用語ではないかもしれません)。しかし、この値は無意味であることが「既知」です。サーバーは存在するが、値を取得するプロセスがクラッシュした場合、それを測定することは有効ですが、失敗して「不明な」値が発生します。
exhuma

2
@exhumaそれでは、「該当なし」と説明します。
ヴィンセント

6
好奇心から、「空」が単にスケールのゼロに等しくない場合、どのような測定をしていますか?「不明」/「欠落」センサーが接続されていない場合や、センサーの生の出力が何らかの理由でゴミである場合など、有用であることがわかりますが、考えられるすべてのケースで「空」がより一貫している可能性がありますで表される0[]または{}(スカラー0、空のリスト、および空のマップ、それぞれ)。また、その「欠落」/「不明」の値は、基本的にまさにその目的です。オブジェクトがnull存在する可能性があるが、存在しないことを表しています。
ニックハートリー

7
これに使用する解決策が何であれ、そもそもNULLを排除したいと考えた問題と同様の問題を抱えているかどうかを自問してください。
レイ

回答:


85

少なくとも関数型言語でこれを行う一般的な方法は、差別化された結合を使用することです。これは、有効なint、「欠損」を示す値、または「不明」を示す値のいずれかである値です。F#では、次のようになります。

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

そのMeasurement場合、値はReadingint値を持つa 、またはa Missing、またはUnknown生データvalue(必要な場合)になります。

ただし、差別化されたユニオンまたは同等の言語をサポートする言語を使用していない場合、このパターンはあまり使用されません。そこで、たとえば、3つのうちのどれが正しいデータを含むかを示す列挙型フィールドを持つクラスを使用できます。


7
OO言語で合計タイプを実行できますが、それらを動作させるためのかなりのボイラープレートがあります。stackoverflow.com/ questions
3151702 /

11
「[非機能言語の言語で]このパターンは、あなたにとってあまり役に立たないでしょう」— OOPで非常に一般的なパターンです。GOFにはこのパターンのバリエーションがあり、C ++などの言語はそれをエンコードするためのネイティブコンストラクトを提供します。
コンラッドルドルフ

14
@jk。はい、彼らは数えません(まあ、彼らはそうするでしょう。彼らは安全性の欠如のためにこのシナリオでは非常に悪いです)。私はstd::variant(そしてその精神的な先祖)を意味しました。
コンラッドルドルフ

2
@Ewanいいえ、「測定は…または…のいずれかのデータ型です」と言っています。
コンラッドルドルフ

2
@DavidArno DUがなくても、OOPにはこのための「標準的な」ソリューションがあります。これは、有効な値と無効な値のサブクラスを持つ値のスーパークラスを持つことです。しかし、それはおそらく行き過ぎです(実際には、他の回答に示されているように、ほとんどのコードベースはサブクラスポリモーフィズムを避けて、このフラグを支持しているようです)。
コンラッドルドルフ

58

モナドが何であるかまだわからない場合、今日は学ぶのに最適な日です。オブジェクト指向プログラマー向けの優しい紹介があります:

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

あなたのシナリオは、Nullable<T>C#やOptional<T>他の言語でも知られている「多分モナド」の小さな拡張です。

モナドを表す抽象型があるとしましょう:

abstract class Measurement<T> { ... }

次に、3つのサブクラス:

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 ...}

バインドの実装が必要です。

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 ...
  }

これから、この簡易バージョンのバインドを記述できます。

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

これで完了です。あなたは持っているMeasurement<int>手に。あなたはそれを2倍にしたい:

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

そして、ロジックに従ってください。もしmあるEmpty<int>その後、asStringIS Empty<String>、優れ。

同様に、

Measurement<int> First()

そして

Measurement<double> Second(int i);

次に、2つの測定値を組み合わせることができます。

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

そして再び、場合がFirst()ありEmpty<int>、その後dEmpty<double>というように。

重要なステップは、バインド操作を正しくすることです。それについて真剣に考えてください。


4
モナドは(ありがたいことに)理解するよりもはるかに使いやすいです。:)
グラン

11
@leftaroundabout:髪を裂くような区別をしたくなかったからです。オリジナルのポスターが指摘しているように、多くの人々はモナドを扱うことに関して自信に欠けています。簡単な操作の専門用語を多く含むカテゴリー理論の特性化は、自信と理解を養うことに対して機能します。
エリックリッパー

2
だからあなたのアドバイスは交換することですNullNullable、いくつかの定型コード+?:)
エリックドゥミニル

3
@クロード:あなたは私のチュートリアルを読む必要があります。モナドは、特定の規則に従い、一連の操作を結合する機能を提供するジェネリック型ですMeasurement<T>。この場合、モナド型です。
エリックリッパー

5
@daboross:ステートフルモナドはモナドを紹介する良い方法であることに同意しますが、状態を保持することはモナドを特徴付けるものだとは思いません。関数のシーケンスを一緒にバインドできるという事実は、説得力のあることだと思います。ステートフルネスは実装の詳細にすぎません。
エリックリッパー

18

この場合、Null Object Patternのバリエーションが役立つと思います。

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
    };
}

それを構造体に変換し、Equals / GetHashCode / ToStringをオーバーライドしint、からまたはへの暗黙的な変換を追加できます。NaNのような動作が必要な場合は、独自の算術演算子を実装することもできます。Measurement.Unknown * 2 == Measurement.Unknown

とは言っても、C#はNullable<int>すべてを実装していますが、唯一の注意点は、異なるタイプのnullsを区別できないことです。私はJavaの人ではありませんが、Java OptionalIntの言語は似ており、他の言語にはOptional型を表す独自の機能がある可能性が高いと理解しています。


6
私がこのパターンで見た最も一般的な実装には、継承が含まれます。2つのサブクラス、MissingMeasurementとUnknownMeasurementの場合があります。親のMeasurementクラスのメソッドを実装またはオーバーライドできます。+1
グレッグブルクハルト

2
Null Object Patternのポイントは、無効な値で失敗せず、何もしないということではありませんか?
クリスウォーラート

2
@ChrisWohlertこの場合、オブジェクトは本当に以外の任意のメソッドはありません。Valueあなたが変換できないと絶対に失敗するゲッター、Unknownに背中をint。測定にSaveToDatabase()メソッドなどがある場合、現在のオブジェクトがnullオブジェクトの場合、適切な実装ではおそらくトランザクションを実行しません(シングルトンとの比較またはメソッドのオーバーライドによる)。
マチェイスタチャウスキー

3
@MaciejStachowskiええ、私はそれが何もしないべきだと言っているのではなく、Null Object Patternはぴったりではないと言っています。あなたのソリューションはうまくいくかもしれませんが、私はそれをNull Object Patternとは呼びません。
クリスウォーラート

14

文字通り整数を使用しなければならない場合、考えられる解決策は1つだけです。「欠落」および「不明」を意味する「マジックナンバー」として可能な値の一部を使用します

例: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 -ダニーPflughoeft

8
@ BlueRaja-DannyPflughoeft実際には、ネストされた構造を持つOPの説明に非常によく適合しています。我々はもちろんの適切なタイプの別名(または「のnewtype」)をご紹介したい許容なるために-しかし、type Measurement = Option<Int>整数または空読みした結果についてはokです、そしてそうでOption<Measurement>取らかをされている可能性があり、測定のためには、 。
ベルギ

7
@arp「NaNに近い整数」?それが何を意味するのか説明してもらえますか?数字は、数字ではない何かのまさに概念に「近い」と言うのは幾分直観に反するように思われます。
ニックハートリー

3
@Nic Hartley私たちのシステムでは、「自然に」可能な最小の負の整数のグループがNaNとして予約されていました。これらのバイトが正当なデータ以外のものを表すさまざまな理由をエンコードするために、そのスペースを使用しました。(それは数十年前だったと私は詳細の一部をfuzzedているかもしれませんが、あなたはそれで数学を行うにしようとした場合、それがNaNをスローにするために、整数値に入れることができますビットのセットは間違いなくありました。
arpを

11

あなたの変数は、浮動小数点数の場合は、IEEE754(ほとんどの最新のプロセッサや言語によってサポートされている浮動小数点数の標準)が背中を持っている:それはあまり知られていない機能ですが、標準では1ではなく、定義し、家族全員NaN(not-a-number)値。任意のアプリケーション定義の意味に使用できます。たとえば、単精度浮動小数点数では、2 ^ {22}種類の無効な値を区別するために使用できる22の空きビットがあります。

通常、プログラミングインターフェイスはそのうちの1つだけを公開します(例:Numpyのnan)。明示的なビット操作以外に他の方法を生成する組み込み方法があるかどうかはわかりませんが、それはいくつかの低レベルのルーチンを書くだけの問題です。(設計上、a == bそれらの1つがNaNである場合は常にfalseを返すため、それらを区別するためにも必要になります。)

それらを使用することは、正しく伝播して無効性を通知するため、無効なデータを通知するために独自の「マジックナンバー」を再発明するよりも優れています。たとえば、average()関数を使用し、あなたの特別な価値。

唯一のリスクは、ライブラリがかなりあいまいな機能であるため、ライブラリを正しくサポートしていないことです。たとえば、シリアル化ライブラリは、それらをすべて同じように「フラット化」する場合がnanあります(ほとんどの目的で同等です)。


6

David Arnoの答えに従って、OOPでの差別化された結合、Scala、Java 8の機能タイプ、またはVavrFugueなどのJava FPライブラリが提供するようなオブジェクト関数型スタイルのようなものを、かなり感じられます次のように書くのが自然です:

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(別名Maybe)(値またはエラーのEitherいずれかを含むオブジェクト)や(ここで使用できる成功値または失敗値のいずれかを含むオブジェクト)などの他のツールを提供します。


2

問題の理想的な解決策は、既知の障害と既知の信頼できない測定の違いに関心がある理由と、サポートするダウンストリームプロセスに依存します。この場合の「下流プロセス」は、人間のオペレーターや仲間の開発者を除外しないことに注意してください。

nullの「2番目のフレーバー」を考え出すだけでは、下流の一連のプロセスに、適切な一連の動作を導き出すのに十分な情報が提供されません。

代わりに、ダウンストリームコードによって行われている悪い動作のソースに関するコンテキストの前提に依存している場合、その悪いアーキテクチャを呼び出します。

失敗の理由と既知の理由のない失敗を区別するのに十分な知識があり、その情報が将来の動作を知らせる場合、その知識を下流に伝えるか、インラインで処理する必要があります。

これを処理するためのいくつかのパターン:

  • 合計タイプ
  • 差別された組合
  • 操作の結果を表す列挙型と結果のフィールドを含むオブジェクトまたは構造体
  • 通常の操作では達成できないマジックストリングまたはマジックナンバー
  • この使用が慣用的な言語の例外
  • これらの2つのシナリオを区別し、単に使用するだけでは実際には価値がないことを認識します null

2

エレガントなソリューションではなく「何かをする」ことに関心がある場合、迅速かつ汚いハックは単に「不明」、「欠落」、「数値の文字列表現」という文字列を使用することです。文字列から変換され、必要に応じて使用されます。これを書くよりも早く実装され、少なくともいくつかの状況では完全に適切です。(私は今、ダウン投票の数で賭けプールを形成しています...)


「何かを成し遂げる」ことに言及して賛成。
さようならMsチップス

4
これは、NULLの使用と同じ問題のほとんどに苦しむことに気付く人もいるでしょう。つまり、NULLチェックの必要性から「不明」および「欠落」チェックの必要性に切り替わるだけで、あなたがチェックを忘れた唯一の指標としての不運。NULLチェックが欠落している場合でも、リンターがそれらをキャッチできるという利点がありますが、これはそれを失います。ただし、「不明」と「欠落」の区別が追加されるため、そこではNULLに
勝ってい

2

質問が「単一のintを返すメソッドから2つの無関係な情報を返すにはどうすればよいですか。戻り値をチェックしたくないので、nullが悪いので、使用しないでください。」

何を渡したいか見てみましょう。intを渡せない理由について、intまたはint以外の論理的根拠のいずれかを渡しています。質問は2つの理由しかないと主張しますが、列挙型を作成したことがある人なら誰でもリストが大きくなることを知っています。他の理論的根拠を指定する範囲は理にかなっています。

最初は、これは例外をスローするための良いケースのように見えます。

呼び出し側に戻り値の型ではない特別な何かを伝えたい場合、例外はしばしば適切なシステムです:例外はエラー状態のためだけではなく、多くのコンテキストと理論的根拠を返して、なぜできるのかを説明することができます今日はありません。

これは、保証付き有効なintを返すことができる唯一のシステムであり、intを取るすべてのint演算子とメソッドが、nullやマジック値などの無効な値をチェックする必要なく、このメソッドの戻り値を受け入れることができることを保証します。

しかし、例外は、名前が示すように、これが例外的なケースであり、通常のビジネスコースではない場合にのみ有効なソリューションです。

そして、try / catch and handlerは、そもそも反対であったnullチェックと同じくらい定型的なものです。

そして、呼び出し元にtry / catchが含まれていない場合、呼び出し元の呼び出し元はそれを繰り返す必要があります。


素朴な2番目のパスは、「これは測定値です。負の距離測定値はほとんどありません」と言うことです。したがって、一部の測定Yについては、次の定数を使用できます。

  • -1 =不明、
  • -2 =測定不能、
  • -3 =回答を拒否、
  • -4 =既知だが機密、
  • -5 =ムーンフェイズによって異なります。表5aを参照してください。
  • -6 = 4次元、タイトルで指定された測定値、
  • -7 =ファイルシステム読み取りエラー、
  • -8 =将来の使用のために予約済み、
  • -9 =平方/立方体なので、YはXと同じですが、
  • -10 =はモニター画面であるため、X、Y測定を使用しません。画面の対角線としてXを使用し、
  • -11 =領収書の裏面の測定値を書き留め、判読不能になったが、5または17だったと思う
  • -12 = ...アイデアが得られます。

これは、多くの古いCシステムで行われている方法であり、intに真の制約がある現代のシステムでさえ、何らかのタイプの構造体またはモナドにラップすることはできません。

測定値が負になる可能性がある場合は、データ型を大きくし(たとえば、long int)、intの範囲よりもマジック値を高くし、理想的にはデバッガーに明確に表示される値で開始します。

ただし、単にマジックナンバーを持たせるのではなく、個別の変数として使用するのには十分な理由があります。たとえば、厳密なタイピング、保守性、および期待への準拠。


3番目の試みでは、非整数値を持つことが通常のビジネスコースである場合を検討します。たとえば、これらの値のコレクションに複数の非整数エントリが含まれる場合があります。これは、例外ハンドラーが間違ったアプローチである可能性があることを意味します。

その場合、intとその理論的根拠を渡す構造の良い例に見えます。繰り返しますが、この理論的根拠は上記のようなconstになりますが、両方を同じintに保持する代わりに、構造の別個の部分として保存します。最初に、原理が設定されている場合、intは設定されないというルールがあります。しかし、私たちはもはやこの規則に縛られていません。必要に応じて、有効な数値の理論的根拠も提供できます。

いずれにせよ、呼び出すたびに、理論的根拠をテストしてintが有効かどうかを確認し、理論的根拠に基づいてint部分を引き出して使用するボイラープレートが必要です。

これは、「nullを使用しないでください」の背後にある理由を調査する必要がある場所です。

例外と同様に、nullは例外的な状態を意味します。

呼び出し元がこのメソッドを呼び出して、構造の「合理的」部分を完全に無視し、エラー処理のない数字を期待し、ゼロを取得した場合、ゼロを数字として処理し、間違っています。マジックナンバーを取得した場合、それは数字として扱われ、間違っています。しかし、nullを取得した場合、うまくいくはずなので、転倒します。

したがって、このメソッドを呼び出すたびに戻り値のチェックを行う必要がありますが、帯域内または帯域外にかかわらず無効な値を処理し、try / catch、「合理的な」コンポーネントの構造体、intマジックナンバーの場合、またはnullの場合はintをチェックします...

代わりに、無効なintと「私の犬がこの測定値を食べた」のような理論的根拠を含む可能性のある出力の乗算を処理するには、その構造の乗算演算子をオーバーロードします。

...そして、このデータに適用される可能性のあるアプリケーション内の他のすべての演算子をオーバーロードします。

...そして、intを取る可能性のあるすべてのメソッドをオーバーロードします。

...そしてすべてのものをオーバーロードはする必要があります、まだそれは常にあなたがそれを呼び出している時点で有効なint型であるかのようにあなたは、この1つの方法の戻り値の型を扱うことができるだけのように、無効なint型のためのチェックが含まれています。

したがって、元の前提はさまざまな点で間違っています。

  1. 無効な値がある場合、値を処理しているコードのどの時点でも、それらの無効な値のチェックを避けることはできません。
  2. int以外を返す場合、intを返さないので、intのように扱うことはできません。演算子のオーバーロードにより、ふりをすることができますが、それは単なるふりです。
  3. マジックナンバー(NULL、NAN、Inf ...を含む)を持つintは、もはや実際にはintではなく、貧乏人の構造体です。
  4. nullを回避してもコードの堅牢性は向上せず、intの問題が隠されるか、複雑な例外処理構造に移動するだけです。

1

私はあなたの質問の前提を理解していませんが、ここに額面の答えがあります。欠落または空の場合は、math.nan(数字ではない)を行うことができます。任意の数学演算を実行できますmath.nanが、残りmath.nanます。

None不明な値には(Pythonのnull)を使用できます。とにかく未知の値を操作するべきではなく、一部の言語(Pythonはそれらの1つではありません)には、値が非nullの場合にのみ操作が実行されるように、特別なnull演算子があります。

他の言語にはガード句(SwiftやRubyなど)があり、Rubyには条件付き早期復帰があります。

私はこれをいくつかの異なる方法でPythonで解決したのを見ました:

  • 数値データは通常エンティティに関するものであり、測定時間があるため、ラッパーデータ構造を使用します。ラッパーは、次のようなマジックメソッドをオーバーライド__mult__して、UnknownまたはMissingの値が発生したときに例外が発生しないようにすることができます。ナンピーとパンダはそのような能力を持っているかもしれません。
  • センチネル値(your Unknownまたは-1 / -2など)およびifステートメント
  • 個別のブール値フラグ付き
  • 遅延データ構造の場合-関数は構造に対して何らかの操作を実行してから戻り、実際の結果を必要とする最も外側の関数が遅延データ構造を評価します
  • 遅延パイプライン操作-前のものと同様ですが、これは一連のデータまたはデータベースで使用できます

1

値をメモリに保存する方法は、言語と実装の詳細に依存します。あなたが言っているのは、オブジェクトがプログラマーに対してどう振る舞うべきかということだと思います。(これが質問の読み方です。間違っているかどうか教えてください。)

あなたはすでにあなたの質問でそれに対する答えを提案しています:数学的な操作を受け入れ、例外を発生させることなくそれ自体を返す独自のクラスを使用してください。nullチェックを回避するため、これが必要だと言います。

解決策1:nullチェックを避けないでください

Missing次のように表すmath.nan
UnknownことができますNone

あなたが複数の値を持っている場合は、できるfilter()だけではありません値に操作を適用するUnknownMissing、または何でもあなたが機能するために無視したい値。

単一のスカラーに作用する関数のnullチェックが必要なシナリオは想像できません。その場合は、nullチェックを強制することをお勧めします。


解決策2:例外をキャッチするデコレーターを使用する

この場合、Missing上げることができるMissingExceptionUnknown上げることができるUnknownException操作は、その上で実行されている場合。

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

このアプローチの利点は、の性質ということであるMissingとは、Unknownあなたが明示的に抑制されるためにそれらを求める場合にのみ抑制されています。もう1つの利点は、このアプローチが自己文書化であるということです。すべての関数は、未知または欠落を予期するかどうかと、その関数の方法を示します。

MissingがMissingを取得することを期待しない関数を呼び出すと、関数はすぐに発生し、エラーが発生した場所を静かに失敗して呼び出しチェーンのMissingを伝播する代わりに正確に表示します。不明の場合も同様です。

sigmoidのデコレータが例外をキャッチするためsinMissingまたはを予期していなくても、を呼び出すことができます。Unknownsigmoid


1
同じ質問に2つの回答を投稿することのポイントは何だろう(これはあなたの前の回答であり、何か問題がありますか?)
gnat

@gnatこの回答は、著者が示す方法でそれを行うべきではない理由を提供します.2つの回答を異なるアイデアと統合する面倒なことはしたくありませんでした-独立して読むことができる2つの回答を書く方が簡単です。他の人の無害な推論をどうしてそんなに気にしているのか理解できない
noɥʇʎԀʎzɐɹƆ

0

サーバー内のCPUの数を取得すると仮定します。サーバーの電源が切れているか、廃棄されている場合、その値は存在しません。意味をなさない測定値になります(「欠落」/「空」は最良の用語ではないかもしれません)。しかし、この値は無意味であることが「既知」です。サーバーは存在するが、値を取得するプロセスがクラッシュした場合、その測定は有効ですが、失敗して「不明な」値が返されます。

これらは両方ともエラー状態のように聞こえるので、ここでの最良のオプションはget_measurement()、これらの両方をただちに例外としてスローすることです(それぞれDataSourceUnavailableExceptionまたはなどSpectacularFailureToGetDataException)。その後、これらの問題のいずれかが発生した場合、データ収集コードはすぐに(後者の場合に再試行するなどして)反応することができ、データからデータを正常に取得できる場合にget_measurement()のみを返すint必要がありますソース-そして、あなたintは有効であることを知っています。

状況が例外をサポートしていないか、例外をあまり利用できない場合、適切な代替手段はエラーコードを使用することget_measurement()です。これはCの慣用的なパターンです。実際の出力は入力ポインターに格納され、エラーコードが戻り値として返されます。


0

与えられた答えは問題ありませんが、空の値と不明な値の間の階層関係を反映していません。

  • 最も高いものは不明です。
  • 次に、値を使用する前に、最初に空を明確にする必要があります。
  • 最後に計算するがあります

Uい(抽象化に失敗したため)、しかし完全に動作するのは(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サプライヤによって取得されます。値が空の場合、intサプライヤは空の例外をスローするか、空と評価します(再帰的に上向き)。メイン式はすべての値を接続し、場合によっては空(値/例外)も返します。不明な値は、例外をスローして評価を無効にします。

値はおそらく、Javaバウンドプロパティのように変更可能であることをリスナーに通知するように観察可能です。

要するに、空の状態と不明な状態が追加された値を必要とする繰り返しパターンは、バインドされたプロパティデータモデルのようなスプレッドシートの方が優れている可能性があることを示しているようです。


0

はい、いくつかの言語には複数の異なるNAタイプの概念が存在します。より意味のある統計的なもの(つまり、Missing-At-Random、Missing-Completely-At-Random、Missing-Not-At-Randomの大きな違い)でより重要です。

  • ウィジェットの長さのみを測定する場合、「センサー障害」、「電源切断」、または「ネットワーク障害」を区別することは重要ではありません(ただし、「数値オーバーフロー」は情報を伝えます)

  • しかし、たとえばデータマイニングや調査で、回答者に収入やHIVステータスなどを尋ねる場合、「不明」の結果は「回答の拒否」とは異なり、後者を推測する方法に関する以前の仮定は傾向があることがわかります前者とは異なります。したがって、SASなどの言語は、複数の異なるNAタイプをサポートしています。R言語はそうではありませんが、ユーザーは非常に頻繁にそれをハックしなければなりません。パイプラインの異なるポイントにあるNAは、非常に異なるものを示すために使用できます。

  • 単一のエントリに対して複数のNA変数がある場合もあります(「複数の代入」)。例:人の年齢、郵便番号、学歴、収入のいずれもわからない場合、収入を帰属させることは困難です。

サポートしていない汎用言語でさまざまなNAタイプをどのように表現するかについては、一般に、整数の浮動小数点NaN(整数の変換が必要)、enumまたはセンチネル(たとえば、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、欠損値をサポートする他の機能言語は何ですか?欠損値をサポートしていても、1行のコードだけで統計的手法でそれらを埋めることはできないと確信しています。
ilhan

-1

*代わりに、演算子の機能を変更できない理由はありますか?

ほとんどの答えには、ある種のルックアップ値が含まれますが、この場合は数学演算子を修正する方が簡単かもしれません。

その後、同様の持つことができるだろうempty()/ unknown()あなたのプロジェクト全体の機能を。


4
これは、すべての演算子をオーバーロードする必要があることを意味します
パイプ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.