1

Consider the following model:

var threads = {
    "thread1": {
        "upvotes": {
            "1": true,
            "3": true,
            "4": true,
            "10": true
        },
        "downvotes": {
            "2": true,
            "5": true,
            "8": true,
            "9": true
        }
    },
    "thread2": {
        "upvotes": {
            "1": true,
            "3": true,
            "7": true,
            "10": true
        },
        "downvotes": {
            "2": true,
            "6": true,
            "8": true,
            "9": true
        }
    },
    "thread3": {
        "upvotes": {
            "1": true,
            "4": true,
            "7": true,
            "10": true
        },
        "downvotes": {
            "2": true,
            "5": true,
            "8": true
        }
    }
}

I'd like to iterate over this model, getting a count of each instance in which each number in upvotes coincides with each of the other numbers in upvotes. I'm doing the following to achieve a crude approximation of this:

var us = 0;
var youObj = {};
var matchesObj = {};
members = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'];

var getAlignments = function(me, you) {
    for (var thread in threads) {
        if ((Object.keys(threads[thread].upvotes).includes(me)) && (Object.keys(threads[thread].upvotes).includes(you))) {
            us++            
        }
    }
    if (us > 0) {
        youObj[you] = us
        matchesObj[me] = youObj
        us = 0;
    }
}

for (var i = 0; i < members.length; i++) {
    var me = members[i]
    for (var j = 0; j < members.length; j++) {
        var you = members[j]
        getAlignments(me, you)      
    }
}

console.log(matchesObj)

This logs the following to console:

{ 
  '1': { '1': 3, '3': 2, '4': 2, '7': 2, '10': 3 },
  '3': { '1': 3, '3': 2, '4': 2, '7': 2, '10': 3 },
  '4': { '1': 3, '3': 2, '4': 2, '7': 2, '10': 3 },
  '7': { '1': 3, '3': 2, '4': 2, '7': 2, '10': 3 },
  '10': { '1': 3, '3': 2, '4': 2, '7': 2, '10': 3 } 
}

As you can see, the child objects are all identical. The reason for this is obvious. The last object assigned to its parent in the loop overwrites the previous object. Each property key in the { '1': 3, '3': 2, '4': 2, '7': 2, '10': 3 } object represents a number that coincides with '10' in each thread's upvotes object and each property value represents a count of these coincidences.

What I need is this type of list for each number that coincides with other numbers in upvotes. This seems like such a basic problem, but I'm struggling with it right now.

2
  • please add members. Commented Mar 13, 2017 at 17:18
  • Whoops! Question updated. Members, is really just another crude aspect of this to be honest. It seems like there should be a way of iterating over the property keys that are already in upvotes instead of iterating over a list of members that may or may not have ever upvoted. Commented Mar 13, 2017 at 17:19

1 Answer 1

2

Why not use a double nested loop over the keys and get the count.

var threads = { thread1: { upvotes: { 1: true, 3: true, 4: true, 10: true }, downvotes: { 2: true, 5: true, 8: true, 9: true } }, thread2: { upvotes: { 1: true, 3: true, 7: true, 10: true }, downvotes: { 2: true, 6: true, 8: true, 9: true } }, thread3: { upvotes: { 1: true, 4: true, 7: true, 10: true }, downvotes: { 2: true, 5: true, 8: true } } },
    result = {};

Object.keys(threads).forEach(function (k) {
    Object.keys(threads[k].upvotes).forEach(function (l) {
        result[l] = (result[l] || 0) + 1;
    });
});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Solution with pairs.

var threads = { thread1: { upvotes: { 1: true, 3: true, 4: true, 10: true }, downvotes: { 2: true, 5: true, 8: true, 9: true } }, thread2: { upvotes: { 1: true, 3: true, 7: true, 10: true }, downvotes: { 2: true, 6: true, 8: true, 9: true } }, thread3: { upvotes: { 1: true, 4: true, 7: true, 10: true }, downvotes: { 2: true, 5: true, 8: true } } },
    result = {},
    result2 = {};

Object.keys(threads).forEach(function (k) {
    var keys = Object.keys(threads[k].upvotes);
    keys.forEach(function (l) {
        result[l] = (result[l] || 0) + 1;
        result2[l] = result2[l] || {};
        keys.forEach(function (m) {
            if (l !== m) {
                result2[l][m] = (result2[l][m] || 0) + 1;
            }
        });
    });
});


console.log(result);
console.log(result2);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

4 Comments

This answer suggests the use of double nest loops over the keys, which is good enough for me to take it from there. But this solution itself only counts the occurrences of the keys. The original question asks for counts of coinciding keys. For example, how many times does upvotes contain these two keys together? 1 and 10: 3 times. The solution that answers the specific question does this for every key. Please consider editing your answer to address the question specifically.
how would the result of the wanted feature look like with the given data?
{ '1': { '3': 2, '4': 2, '7': 2, '10': 3 }, '3': { '1': 2, '4': 1, '7': 1, '10': 2 }, '4': { '1': 2, '3': 1, '7': 1, '10': 2 }, '7': { '1': 2, '3': 1, '4': 1, '10': 2 }, '10': { '1': 3, '3': 2, '4': 2, '7': 2 } } I apologize if the model naming doesn't lend itself particularly well to this goal, but the idea is that we want a count for each key's coincidence with each of the other keys. So looking at the first object here, we see that '1' occurs in upvotes with '3' 2 times, with '4' 2 times, with '7' 2 times and with '10' 3 times.
Perfect. Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.