SKU多次元属性状態判定アルゴリズム

SKU多次元属性状態判定アルゴリズム

問題の説明

この問題は、製品属性を選択するシナリオから発生します。たとえば、服や靴を購入するときは、通常、適切な色、サイズ、その他の属性を選択する必要があります。

まずSKUの学術的概念を理解しましょう

最小在庫管理単位 (SKU) は会計用語で、在庫管理で使用可能な最小単位として定義されます。たとえば、繊維製品の場合、SKU は通常、仕様、色、スタイルを表しますが、チェーン小売店では、単一の製品が SKU と呼ばれることもあります。最小在庫管理単位は、異なる商品の最小販売単位を区別できます。これは、商品の調達、販売、物流、財務管理の科学的管理、および POS および MIS システムのデータ統計の要件です。通常、管理情報システムのコードに対応します。 —— Wikipedia より 最小在庫管理単位

簡単に言うと、上記の例を組み合わせると、SKUはショッピングサイトで購入する最終製品であり、上記の画像で選択された対応する属性は、色は黒、サイズは37です。

まず、バックエンドのデータ構造を見てみましょう。一般的には次のようになります。線形配列で、各要素は現在の SKU を記述するマップです。例:

  1. [
  2. { "色" : "赤" "サイズ" : "ラージ" "モデル" : "A" "SKUID" : "3158054" },
  3. { "色" : "白" "サイズ" : "中" "モデル" : "B" "SKUID" : "3133859" },
  4. { "色" : "青" "サイズ" : "小" "モデル" : "C" "skuId" : "3516833" }
  5. ]

当然、フロントエンドに表示するときにはグループ化する必要があります。その目的は、ユーザーが属性ディメンションに基づいて選択できるようにすることです。グループ化されたデータは、おおよそ次のようになります。

  1. {
  2. "色" : [ "赤" "白" "青" ],
  3. 「サイズ」 : [ 「大」 「中」 「小」 ],
  4. 「モデル」 : [ 「A」 「B」 「C」 ]
  5. }

ウェブページ上の対応するUIはおそらく次のようになります

このとき、問題が生じます。これらのサブ属性が形成できるセット(ユーザーの選択パス)は、実際に形成できるセットよりもはるかに大きくなります。たとえば、上記の属性セットは、直積に組み合わせることができます。次のシーケンスに組み合わせることができます。

  1. [
  2. [ "赤" , "大きい" , "A" ], // ✔
  3. [ "赤" "大きい" "B" ],
  4. [ "赤" "大きい" "C" ],
  5. [ "赤" "真ん中" "A" ],
  6. [ "赤" "中" "B" ],
  7. [ "赤" "中" "C" ],
  8. [ "赤" "小さい" "A" ],
  9. [ "赤" "小さい" "B" ],
  10. [ "赤" "小さい" "C" ],
  11. [ "白" "大きい" "A" ],
  12. [ "白" "大きい" "B" ],
  13. [ "白" "大きい" "C" ],
  14. [ "白" "真ん中" "A" ],
  15. [ "白" , "真ん中" , "B" ], // ✔
  16. [ "白" "中" "C" ],
  17. [ "白" "小さい" "A" ],
  18. [ "白" "小" "B" ],
  19. [ "白" "小" "C" ],
  20. [ 「青」 「大きい」 「A」 ]、
  21. [ 「青」 「大きい」 「B」 ]、
  22. [ 「青」 「大きい」 「C」 ]、
  23. [ 「青」 「中」 「A」 ]、
  24. [ 「青」 「中」 「B」 ]、
  25. [ "青" "中" "C" ]、
  26. [ 「青」 「小」 「A」 ]、
  27. [ "青" "小" "B" ],
  28. [ "青" "小さい" "C" ] // ✔
  29. ]

式によれば、それぞれが 3 つの要素のサブセットである 3 つの要素のセットは、3 の 3 乗の直積、つまり 27 を形成できます。ただし、ソース データでは 3 つの組み合わせしか形成できません。

この場合、使用できないパスを事前に特定し、グレー表示にしてユーザーに通知するのが最善です。そうしないと、誤解を招くことになります。

ルールを決める

下の図を見てください。現在選択されている製品の属性として red を定義した場合、つまり現在選択されている製品は red-big-A である場合、選択されていない他の属性がオプションのパスを形成できるかどうかをどのように確認できるでしょうか。

ルールは次のとおりです。現在のユーザーが白-大きい-A を選択したいが、この選択パスが存在しない場合は、白をグレー表示します。

同様に、blue 属性が使用可能かどうかを確認する場合は、blue-big-A パスが存在するかどうかを確認する必要があります。

回避策

上記のロジックコードによれば、次のようになります。

選択されていないすべての要素をトラバースします: "white", "blue", "medium", "small", "B", "C" すべての属性行をトラバースします: "color", "size", "model" 取得: a) 現在の要素 b) 選択された要素の、現在の要素ではない他の属性 (パスを形成する)

  1. このパスが存在するかどうかを判断します。存在しない場合は、現在の要素をグレー表示します。

a. 問題は解決したようですが…

非常に重要な点を見落としていました。上記の例では白い要素がグレー表示されていますが、実際にはクリック可能です。ユーザーはwhite-middle-Bというパスを選択できるためです。

ユーザーが白をクリックすると、状況はさらに複雑になります。ユーザーが白の要素のみを選択したと仮定します。選択されていない他の要素が選択可能かどうかをどのように判断するのでしょうか。

つまり、「大」、「中」、「小」、「A」、「B」、「C」をグレー表示する必要があるかどうかをどのように判断するのでしょうか。属性内の要素はすべて単一選択であり、現在の属性内の任意の要素が選択可能であるため、「赤」と「青」が選択可能かどうかを確認する必要がないことに注意してください。

問題の大きさを縮小する

まず問題を絞り込みましょう。現在の状況 (白が 1 つだけ選択されている) では、サイズ「大」をグレー表示する必要があることをどのように判断すればよいでしょうか。私たちのロジックによれば、個別に検索する必要があると思われるかもしれません。

  • ホワイト - ラージ - A
  • ホワイト - ビッグ - B
  • ホワイト - 大 - C

存在しない場合は、サイズをグレー表示にすると問題が解決するようです。実際には、これは間違っています。モデルが選択されていないため、white-large が使用可能かどうかのみを知る必要があります。

同時に、別の疑問もあります。選択された項目の数が不確実であり、次元を不確実な数まで増やすことができる場合はどうなるでしょうか?

この場合、以前のアルゴリズムに従うと、実装は非常に複雑になります。今こそ、考え方を変えることを検討する時です。

考え方を調整する

以前は、常に逆の考え方で、グレー表示にして選択できないようにする要素を見つけていました。現在、属性がオプションかどうかを判断する方法を検討しています。さらに、複数の次元の場合、ユーザーはジャンプして選択できます。例えば、ユーザーは2つの要素WhiteとBを選択します。

図1

元のデータを振り返ってみましょう。

  1. [
  2. { "色" : "赤" "サイズ" : "ラージ" "モデル" : "A" "SKUID" : "3158054" },
  3. { "色" : "白" "サイズ" : "中" "モデル" : "B" "SKUID" : "3133859" },
  4. { "色" : "青" "サイズ" : "小" "モデル" : "C" "skuId" : "3516833" }
  5. ]
  6. // 今すぐ
  7. [
  8. [ "red" , "big" , "A" ], // 存在する
  9. [ "白" , "中" , "B" ], // 存在する
  10. [ "青" , "小" , "C" ] // 存在する
  11. ]

明らかに、最初のデータ「赤」、「大きい」、「A」が存在する場合、次のサブ組み合わせが存在する必要があります。

  • 大きい
  • 赤 - 大
  • 赤 - A
  • ビッグ - A
  • 赤 - ビッグ - A

同様に、2 番目のデータ「白」、「中」、「B」が存在する場合、次のサブ組み合わせが存在する必要があります。

  • 真ん中
  • B
  • ホワイト - ミディアム
  • ホワイト - B
  • ミドル - B
  • ホワイト - ミディアム - B

既存のパスのすべてのサブ組み合わせを事前に計算します。これは、アルゴリズムではセットのすべてのサブセットを取得すること、数学ではべき乗セットと呼ばれます。これにより、既存のすべてのパスのテーブルが作成されます。アルゴリズムは次のとおりです。

  1. /**
  2. * 集合(べき集合)のすべての部分集合を取得する
  3. arr = [1,2,3]
  4.  
  5. i = 0、ps = [[]]:
  6. j = 0; j < ps.length => j < 1:
  7. i=0、j=0 ps.push(ps[0].concat(arr[0])) => ps.push([].concat(1)) => [1]
  8. ps = [[], [1]]
  9.  
  10. i = 1, ps = [[], [1]] :
  11. j = 0; j < ps.length => j < 2
  12. i=1、j=0 ps.push(ps[0].concat(arr[1])) => ps.push([].concat(2)) => [2]
  13. i=1、j=1 ps.push(ps[1].concat(arr[1])) => ps.push([1].concat(2)) => [1,2]
  14. ps = [[], [1], [2], [1,2]]
  15.  
  16. i = 2、ps = [[]、[1]、[2]、[1,2]]
  17. j = 0; j < ps.length => j < 4
  18. i=2、j=0 ps.push(ps[0].concat(arr[2])) => ps.push([3]) => [3]
  19. i=2、j=1 ps.push(ps[1].concat(arr[2])) => ps.push([1, 3]) => [1, 3]
  20. i=2、j=2 ps.push(ps[2].concat(arr[2])) => ps.push([2, 3]) => [2, 3]
  21. i=2、j=3 ps.push(ps[3].concat(arr[2])) => ps.push([2, 3]) => [1, 2, 3]
  22. ps = [[], [1], [2], [1,2], [3], [1, 3], [2, 3], [1, 2, 3]]
  23. */
  24. 関数powerset(arr) {
  25. var ps = [[]];
  26. (var i=0; i < arr.length; i++)の場合{
  27. ( var j = 0, len = ps.length; j < len; j++) {
  28. ps.push(ps[j].concat(arr[i]));
  29. }
  30. }
  31. psを返します
  32. }

この既存のサブセット セットを使用して、たとえば図 1 をもう一度見てみましょう。

図1

  • 赤が利用可能かどうかをどのように判断しますか?赤Bが利用可能かどうかを判断するだけです
  • 中央が利用可能かどうかをどのように判断しますか?白-中央-Bが利用可能かどうかを判断する必要があります
  • 2Gがオプションであることを確認するには? White-B-2Gがオプションであることを確認する必要があります

アルゴリズムは次のように説明されます。

  1. 選択されていないすべての要素を反復処理する

a. すべての属性行を走査する

a) 現在の要素、b) 現在の要素以外の属性で選択された他の要素(現在の属性で選択された要素がない場合はスキップ)を取得してパスを形成します。

このパスが存在するかどうかを確認します(既存のすべてのパステーブルを照会します)。存在しない場合は、現在の要素をグレー表示します。

初期バックエンド データを例にとると、生成されるオプションのパス テーブルは次のようになります。パスをトラバーサルせずに検索できるように、パスは区切り文字 "-" で区切られていることに注意してください。

  1. {
  2. "" : {
  3. "SKU" : [ "3158054" , "3133859" , "3516833" ]
  4. },
  5. "赤" : {
  6. "SKU" : [ "3158054" ]
  7. },
  8. "大きい" : {
  9. "SKU" : [ "3158054" ]
  10. },
  11. 「赤-大」 :{
  12. "SKU" : [ "3158054" ]
  13. },
  14. 「あ」 :{
  15. "SKU" : [ "3158054" ]
  16. },
  17. 「赤A」 :{
  18. "SKU" : [ "3158054" ]
  19. },
  20. 「ビッグA」 :{
  21. "SKU" : [ "3158054" ]
  22. },
  23. 「レッドビッグA」 :{
  24. "SKU" : [ "3158054" ]
  25. },
  26. "白" : {
  27. "SKU" : [ "3133859" ]
  28. },
  29. "真ん中" : {
  30. "SKU" : [ "3133859" ]
  31. },
  32. 「白-真ん中」 :{
  33. "SKU" : [ "3133859" ]
  34. },
  35. 「B」 :{
  36. "SKU" : [ "3133859" ]
  37. },
  38. 「ホワイトB」 :{
  39. "SKU" : [ "3133859" ]
  40. },
  41. 「中B」 :{
  42. "SKU" : [ "3133859" ]
  43. },
  44. 「白-ミドル-B」 : {
  45. "SKU" : [ "3133859" ]
  46. },
  47. "青" : {
  48. "SKU" : [ "3516833" ]
  49. },
  50. "小さい" : {
  51. "SKU" : [ "3516833" ]
  52. },
  53. 「青-小」 :{
  54. "SKU" : [ "3516833" ]
  55. },
  56. 「C」 :{
  57. "SKU" : [ "3516833" ]
  58. },
  59. 「ブルーC」 :{
  60. "SKU" : [ "3516833" ]
  61. },
  62. 「小文字のC」 :{
  63. "SKU" : [ "3516833" ]
  64. },
  65. 「青-小-C」 : {
  66. "SKU" : [ "3516833" ]
  67. }
  68. }

このアルゴリズムをより明確に説明するために、別の図を使って説明しましょう。

したがって、上記のロジックによれば、ステータスを計算した後のインターフェースは次のようになります。

さて、この場合、ユーザーがサイズをクリックした場合、どのように操作すればよいでしょうか?

体験を最適化する

現状ではパス red-middle-A が存在しないため、middle をクリックすると、サイズ middle 以外の他の属性の少なくとも 1 つがパス middle に存在しません。

対話型の要件は、現在の属性行が存在しない場合はそれを強調表示し、ユーザーが既存の属性と組み合わせることができる属性を選択できるようにすることです。ユーザーが選択した属性は一度キャッシュされる必要がある

したがって、存在しない属性をクリックすると、インタラクション フローは次のようになります。

  1. 現在の属性が存在するかどうかに関係なく、まず現在の属性を強調表示(選択)します。
  2. 選択した他の属性をすべてクリア
  3. 現在のステータスの下にある他の属性のオプション ステータスを更新します (現在の属性のみを選択します)
  4. 非現在の属性行の他の属性を走査して、キャッシュ内の対応する選択された属性を検索します。
  5. 対応する属性がキャッシュ内に存在する場合 (オプション)、キャッシュ属性がデフォルトで選択され、その他のオプションの状態が再度更新されます。存在しない場合は、現在の属性行が強調表示されます(暗い背景)

このプロセスのフローチャートはおおよそ次のようになります。存在しない属性をクリックすると、「単一選択プロセス」に入ります。

バックエンドデータが次のようになっていると仮定します。

  1. [
  2. { "色" : "赤" "サイズ" : "ラージ" "モデル" : "A" "SKUID" : "3158054" },
  3. { "color" : "white" , "size" : "large" , "model" : "A" , "skuId" : "3158054" }, // アイテムをもう 1 つ追加しました
  4. { "色" : "白" "サイズ" : "中" "モデル" : "B" "SKUID" : "3133859" },
  5. { "色" : "青" "サイズ" : "小" "モデル" : "C" "skuId" : "3516833" }
  6. ]

現在選択されている状態は、白-ビッグ-Aです。

ユーザーがクリックした場合。この時点では、White-Middle は存在しますが、Middle-A は存在しないため、色は白のままにして、モデル属性行を強調表示します。

ホワイトミディアムとマッチできるモデルはBのみであることがわかります。キャッシュの役割は、ユーザーが色を選択する頻度を減らすことです。この時点で、主な機能は基本的に達成されています。例えば、在庫ロジックの処理方法は、属性が存在しないときと同じなので、詳細は説明しません。注意すべき唯一の点は、パワーセットを見つけることの複雑さです。

アルゴリズムの複雑さ

べき乗集合アルゴリズムの時間計算量は O(2^n) です。つまり、各データの属性 (次元) が多いほど、計算量も高くなります。 SKUデータの量は重要ではありません。これは一定の線形成長ですが、ディメンションは指数関数的に増加するためです。

  1. {1} 2^1 = 2
  2. => {},{1}
  3. {1,2} 2^2 = 4
  4. => {},{1},{2},{1,2}
  5. {1,2,3} 2^3 = 8
  6. => {},{1},{2},{3},{1,2},{1,3},{2,3},{1,2,3}
  7. ...

Chrome でいくつかのテストケースを実行した後、このアルゴリズムは非常に非効率的であることがわかります。このアルゴリズムを使用する場合は、次元を合理的な範囲内で制御する必要があります。アルゴリズムの時間計算量が非常に高いだけでなく、生成されるパス テーブルも非常に大きくなり、対応するメモリ使用量も高くなります。

たとえば、10 次元の SKU がある場合、結果のパス テーブルには 2^10 (1024) 個のキー/値のペアが含まれます。

最終的なデモは、こちらでご覧いただけます: sku 多次元属性ステータス判定

関連情報: SKU 組み合わせクエリ アルゴリズムの調査

[この記事は51CTOコラムニストの周其立氏によるオリジナル記事です。転載の際は出典を明記してください。]

この著者の他の記事を読むにはここをクリックしてください

<<:  Java 配列から HashMap へのアルゴリズムの説明

>>:  Tofsee ボットネットは独自のドメイン名生成アルゴリズムを使用する

ブログ    
ブログ    

推薦する

...

AIoT は私たちの未来をどのように定義するのでしょうか?

[[417111]] AI と IoT ほどエキサイティングで重要なテクノロジーの組み合わせはほと...

于聖奇:顔認識技術のリスクと法的規制

デジタル時代の到来により、顔認識技術の開発は大きく進歩しました。顔認識技術は普及し、多くの分野で広く...

...

OpenAIがカスタムコマンド機能を開始、会話ごとに好みや情報を繰り返す必要がなくなる

OpenAIは7月21日、カスタム指示機能のリリースを発表しました。この機能はまずPLUSプランのベ...

...

自動運転のための多視点視覚認識の理解

出力次元の観点から、視覚センサーに基づく知覚方法は、2D知覚と3D知覚に分けられます。視覚システムは...

...

Pythonで簡単な顔認識を実装すると、私はこの星にとても似ていることが判明しました

近年、人工知能の人気が急上昇しており、画像認識、音声認識、機械翻訳、自動運転車など、AI の能力と威...

ジェンセン・フアン:わずか2年で、Nvidiaと業界全体が完全に変わるだろう

黄仁訓は未来について次のように予言した。コンピューティング技術は10年ごとに100万倍に進歩します。...

AI、VR、ブロックチェーンにより、新しい時代は貧しい人々にとっての楽園となるのでしょうか?

今日の社会では貧困がまだ存在しています。 [[275832]]国連開発計画(UNDP)のデータによる...

...

...