1

クライアントから受け取ったオブジェクトを分類しようとしています。

サーバー側では、「ブループリント」を次のように定義しました。

{ // "type1"
    type: 1,
    name: String,
    password: String
}

{ // "type2"
    type: 2,
    user_id: Number,
    action: String
}

{ // "type3", and yes, this says type: 2....
    type: 2,
    object_id: Number,
    action: String
}

クライアントが送信するものに基づいて、次のように分類します。

{ type: 1, name: 'user', password: 'pass' }                    // -> type1
{ type: 1, name: 'user', password: 'pass', remember_me: true } // -> type1
{ type: 2, name: 'user', password: 'pass' }                    // -> N/A
{ type: 2, user_id: 5, action: 'hello' }                       // -> type2
{ type: 2, object_id: 5, action: 'hello' }                     // -> type3

識別は、キー名、値のデータ型、および値の実際の値に基づく必要があります。1秒間に数千のオブジェクトが送信され、数千の設計図が存在する可能性があります。< O(n)したがって、 nが設計図の数である場合に実行できれば便利です。

ブループリントとメタデータを必要なデータ構造に保存できるように、これを最初から作成しています。

助けてくれてありがとう。これについてのアイデアを聞くのを楽しみにしています。

4

3 に答える 3

2

複雑さを軽減する可能性のあるアプローチについてのランダムな考え:

ここでの本当の制限要因は、型のセットをどれだけ削減できるかです。最も明白なアプローチの 1 つは、オブジェクトのキーのみに基づいて何かを行うことです。データに余分なキーがある場合の問題は、 だけに頼ることができないことObject.keys( data ).sort().join(",")です。また、持っているキーのすべての組み合わせを試す必要があります。

// Assuming the "types" list is called "types":
// using underscore.js api
var _ = require('underscore');
var keyMap = _.chain( types ).map(function( typeDef, typeIndex ) {
        // get an index with the definition, in case its 
        return { index: typeIndex, def: typeDef };
    }).groupBy(function( data ) {
        return _.keys( data.def ).sort().join(",");
    }).value();

// empty map needed
keyMap[""] = [];

// assumes sorted key list
function getPossibleMaps( keys ) {
  // if we have a map for this, use it
  if ( keyMap[ keys.join(",") ] ) {
    return keyMap[ keys.join(",") ];
  } else {
    // create a map of possible types by removing every key from the list of keys
    // and then looking for maps that match, cache our result
    return keyMap[ keys.join(",") ] = recursiveMapTest( keys );
  }
}  

function recursiveMapTest( keys ) {
    return _.chain( keys )
      .map(function( key ) {
        return getPossibleMaps( _.without( keys, key ) );
      }).flatten().value();
}

// we must also include "lesser" definitions for each of the key lists we found:
_.each( keyMap, function( results, index ) {
    var keys = index.split(",");
    keyMap[index] = results.concat( recursiveMapTest( keys ) );
});

function getType( data ) {
  function checkType( typeData ) {
    var def = typeData.def;
    return _.every(typeData.def, function( value, key ) {
      // these checks are probably not quite right
      if ( value === null ) {
        return true;
      } else if ( value === Number ) {
        return typeof data[key] === "number" || data instanceof Number;
      } else if ( value === String ) {
        return typeof data[key] === "string" || data instanceof String;
      } else {
        return data[ key ] === value;
      }
    });
  }
  var match = _.find( getPossibleMaps( _.keys( data ).sort() ), checkType );
  return match && match.index;
}

// Retrieve
var clientTypes = [
  { type: 1, name: 'user', password: 'pass' },
  { type: 2, name: 'user', password: 'pass' },
  { type: 2, user_id: 5, action: 'hello' },
  { type: 2, object_id: 5, action: 'hello' },
  { type: 1, name: 'user', password: 'pass', remember_me: true }
];

console.log('Client types:');
for (var i = 0; i < clientTypes.length; i++) {
    var type = clientTypes[i];
    // The type object from the map
    console.log("getType", type, getType(type));
}

jsbin

確かに、これは、着信キー リストの可能性が高いほど、「クイック」ルックアップ テーブルを保存するために消費するメモリが増えることを意味します。


また、すべてに数値型がある場合は、明らかにそれを使用して、そのサブタイプ内の可能な「オブジェクト型」の巨大なチャンクを高速化できます。


そもそもこれを行う必要がないようにするのが最善の策だと思います。オブジェクトでより適切な型ヒントを渡します。

于 2013-02-15T05:05:27.267 に答える
0

あなたはこのようにすることができます

var obj1={ type: 1, name: 'user', password: 'pass' };
var obj2={ type: 2, name: 'user', password: 'pass' };

//match JSON keys
var keys1 = Object.keys(obj1);
var keys2 = Object.keys(obj2);
if (JSON.stringify(keys1) === JSON.stringify(keys2))
console.log("matched all keys");

//match JSON value datatypes
for (var key in obj1) {
   if (typeof(obj1[key]) == typeof(obj2[key]))
   console.log(key +' data type matched');
}

//match 'type' field
if (obj1.type == obj2.type)
console.log("woooo total match");

時間計算量は次のとおりです。

  1. キーマッチは O(n)
  2. フィールドのデータ型の一致は O(n)
  3. タイプ フィールド チェックは O(1)

したがって、JSON が順序付けられている場合、合計は O(n) です。それ以外の場合は、並べ替えにさらに時間がかかります。

于 2013-02-15T04:24:16.277 に答える
0

ブループリントは、オブジェクトまたは配列で送信されます。それらをオブジェクトとして送信できる場合は、型 ID をキーとして使用し、値を型オブジェクトとして使用します。タイプを決定するときは、そのタイプのキーにO(1)時間内にアクセスします。

型を配列として受け取った場合でも、O(n)パスを使用すると、それらをオブジェクトに内部的に格納し、それをハッシュ テーブルとして使用して、実行時に必要な型情報を取得できます。

型自体をキーとして信頼できない場合は、型ごとに一意のキーを生成し、この同じ関数を使用して取得します。

var types = [{ // Will refer to this JSON object as type1
    type: 1,
    name: String,
    password: String
},
{ // type2
    type: 2,
    user_id: Number,
    action: String
},
{ // type3
    type: 2,
    object_id: Number,
    action: String
}];

console.log(types);

// Prepare map
var typeMap = {};
for (var i = 0; i < types.length; i++) {
    var type = types[i];
    typeMap[typeKey(type)] = type;
}
console.log(typeMap);

function typeKey(type) {
    var key = '';
    for (var i in type) {
        if (i == 'type') {
            key += type[i].toString() + ':';
        }
        key += ':' + i;
    }
    return key;
}

function getType(type) {
    return typeMap[typeKey(type)];
}

// Retrieve
var clientTypes = [
    { type: 1, name: 'user', password: 'pass' },
    { type: 2, name: 'user', password: 'pass' },
    { type: 2, user_id: 5, action: 'hello' },
    { type: 2, object_id: 5, action: 'hello' }
];
console.log('Client types:');
for (var i = 0; i < clientTypes.length; i++) {
    var type = clientTypes[i];
    // The type object from the map
    console.log(getType(type));
}

「クライアント」タイプのタイプが見つからない場合は、undefinedgetType から返されます。

http://jsfiddle.net/Kt2sq/1

出力:

Client types:
Object {type: 1, name: function, password: function}
undefined
Object {type: 2, user_id: function, action: function}
Object {type: 2, object_id: function, action: function}
于 2013-02-15T03:30:11.090 に答える