Search code examples
javascriptlogic

Comparison logic on Value and it's Prototype


So, there is a "problem":
You have

let kind_1_ = "some_string"
let kind_2_ = 1234
let kind_3_ = [ "can be string or...", 0, { "some_prop" : "any possible type of value" }, ["...or this"] ]
let kind_4_ = { "even_this" : "will be appropriate" }

const prototype = [ "string", 0, [], {} ]
/* as well as   = [ "string", 0, [] ]       */
/* or as        = [ 0, {} ]                 */
/* and so on... but in most cases with this
   | 4 particular types                     */

So, we have to compare kinds to the prototype. There is only 1 kind and 1 prototype given at the time. My code for this was as simple as this:

let this_will_be_called = (kind, proto) => {
    let bool_to_return = false
    for (let each in proto)
    {
        if (typeof(kind) == typeof(proto)) {
            bool_to_return = true
            return bool_to_return
        }
    }
    return bool_to_return
}

this_will_be_called(kind_any_of_kinds, prototype)

Of course, it's not working the way it should. One Major problem is that you can't effectively compare [] to {}, because they are both of type Object (I know about Array.isArray()). But in case of the following situations, it must return false:

let kind = []
var prototype = [.., {}] /* without [] in here */

/* or this */
let kind = {}
var prototype = [.., []] /* without {} in here */

/* but must return true if: */
let kind = {} /* or let kind = [] */
var prototype = [.., [], {}]

And in the end, it must return false if no types matching.
My logic is explained in this pseudo-code:

FOR every element in prototype:
    IF (type of element == type of kind) and (element is NOT Array):
        return TRUE
    ELSE IF (type of element == type of kind) and (element is Array):
        IF (type of kind is NOT an Object) and (kind is Array):
            return TRUE
        ELSE IF (type of kind is an Object):
            return FALSE
    ELSE IF (type of element == type of kind) and (element is Object) and (element is NOT an Array):
        IF (kind is NOT an Array):
            return TRUE
        ELSE IF (kind is an Array):
            return FALSE
    ELSE:
        return FALSE

Now, I need your attention to audit my logic, because I've completely broke my brain on solving this. Even if above logic works, it's not an elegant solution. So, you could modify it for better performance.

My appreciation on every solution! ;)


Solution

  • First thing first, your prototype is an array, so when you do for..in you get an index of the array, not the item, so you'll need add something like each = proto[each];

    Than, when it comes to detect array vs object, you can detect if kind or each an array compare them and return if the same, if none is an array, proceed as before with typeof.

    let this_will_be_called = (kind, proto) => {
        let bool_to_return = false
        for (let each in proto)
        {
            each = proto[each];
    
            const isKindArray = Array.isArray(kind),
                  isEachArray = Array.isArray(each);
    
            if (isKindArray || isEachArray)
            {
              if (isKindArray && isEachArray)
                return true;
            }
            else if (typeof(kind) == typeof(each)) {
                bool_to_return = true
                return bool_to_return
            }
        }
        return bool_to_return
    }
    
    let kind = []
    let prototype = [ "string", 0, {} ] /* without [] in here */
    console.log(this_will_be_called(kind, prototype), "kind", kind, "proto", prototype)
    
    /* or this */
    kind = {}
    prototype = [ "string", 0, [] ] /* without {} in here */
    console.log(this_will_be_called(kind, prototype), "kind", kind, "proto", prototype)
    
    /* but must return true if: */
    kind = {} /* or let kind = [] */
    prototype = [ "string", 0, [], {} ]
    console.log(this_will_be_called(kind, prototype), "kind", kind, "proto", prototype)
    
    
    /* as well as   = [ "string", 0, [] ]       */
    /* or as        = [ 0, {} ]                 */
    /* and so on... but in most cases with this
       | 4 particular types                     */
    
    kind= "some_string"
    console.log(this_will_be_called(kind, prototype), "kind", kind, "proto", prototype)
    
    kind = 1234
    console.log(this_will_be_called(kind, prototype), "kind", kind, "proto", prototype)
    
    kind = [ "can be string or...", 0, { "some_prop" : "any possible type of value" }, ["...or this"] ]
    console.log(this_will_be_called(kind, prototype), "kind", kind, "proto", prototype)
    
    kind = { "even_this" : "will be appropriate" }
    console.log(this_will_be_called(kind, prototype), "kind", kind, "proto", prototype)