Making a list out of comparison - javascript

For the past few days i've been looking into Javascript and how to make list out of comparison, i found something about arrays, and while i knew that this is what i need, I couldn't understand how it exactly worked with my very little knowledge about Javascript.
I want to make a list, say we have 5 items (let's take a, b, c, d, e as examples) and you're asked to compare one to another (do u like "a" or "d"?) and each time you choose an item it gets a point and it keeps asking you until all the comparisons are made with each item, then a list is made out of those comparisons and the items with the most points are ranked first.
if there is an article, a video, a code that i can analyze, anything would help.
Thanks in advance

Here is an idea of how you could approach it.
So you could have the following setup:
const items = ["a", "b", "c", "d", ...and so on]
const pointsRecord = {"a": 0, "b": 0, "c": 0, ...and so on}
With these two pieces you can build pairs to compare, and keep track of the points of each item.
From your description it sounds like you want to compare every item with every other item on the list. You will probably have to loop through the list twice and build a comparison pair that you can output, or render on the screen.
You could write a function to build comparison pairs to look something like this:
const comparisonPairs = [
[ "a", "b" ],
[ "a", "c" ],
[ "a", "d" ],
[ "b", "c" ],
...and so on
]
With something like this you could iterate through comparisonPairs, render the pair on the screen or output to the terminal. Then take the input, and update the pointsRecord object. Something like:
pointsRecord = {
...pointsRecord, // copy over all the data from the original point record
[selectedItem]: pointsRecord[selectedItem] + 1 // increment the points of the selected item
}
After updating pointsRecord you could move on to the next pair.
To sort them at the end you would just have to run a sort function on the items. Something like:
const sortedItems = items.slice().sort((a, b) => pointsRecord[b] - pointsRecord[a]);
Adding the .slice() creates a new array so you don't alter the original typically this is good practice but you may want to sort the original in place depending on your use case.
This is just one approach. For sure you want to think about how you want to organize the data, which it sounds like you are already doing so you are on the right track. As you are working through this if you find that it's getting messy, updating things, and keeping track of the data, that may be a good sign to re-asses and re-think if there is a better way to store the information.

Related

Best way to group by category a list of products | Javascript

I'm trying to find the best way to group by category and iterate products in O (n) to get some insights from the categories.
I have the sample data:
[
{
"code": 25754,
"description": "ADAPTADOR BLUETOOH USB RECEPTOR DE AUDIO P2",
"price": 5.0,
"stock": 10,
"category": {
"id": 1,
"name": "Adapters"
}
},
{
"code": 20212,
"description": "ADAPTADOR CONECTOR HDMI FEMEA L / FEMEA",
"price": 2.8,
"stock": 20,
"category": {
"id": 2,
"name": "Eletronics"
}
},
]
I need to invert the relationship, having a list of categories with corresponding products, and for that i wrote this solution
function group_by_categories(products) {
const categories = {}
for (const product of products) {
const { category, ...cleanedProduct } = product
categories[category.id] = categories[category.id] || category
categories[category.id].products = categories[category.id].products || []
categories[category.id].products.push(cleanedProduct)
}
return Object.values(categories)
}
// returns
[
{ id: 1, name: 'Adapters', products: [ [Object] ] },
{ id: 2, name: 'Eletronics', products: [ [Object] ] }
]
But I am struggling in two things.
Is it the best way to reverse the relationship? How can I replicate this in another language like C, where I have no objects to use as unique keys?
Once you have this type of data, the only way to iterate categories and products (see how many items a category has, for example) is in O (n²)?
I appreciate all the help, even if you can only answer one question. Also, sorry for my bad English, I'm trying to be as clear as possible here.
So you have 3 issues. 1) Use the code/id as keys instead, 2) Use sets instead of arrays, and 3) use an appropriate data structure to avoid duplicating work that you've already done.
You really just want to map the connections not all the data. I believe code is probably unique to the product, so that is your key. Your category id is also likely unique, so you only need to consider that. The mapping structures should only concern themselves with the minimal amount of unique data. This may increase performance a fair bit as well as the amount of data that get's copied is probably 1/10 to 1/100 of yours in terms of # of characters (of course translating that exactly to time saved is difficult). Of course, that's a minor point compared to the O(N^2) performance, but just that would likely speed things up by a bit by that alone.
You should be using sets as well as the hash (object). Idea here is O(1) lookup, O(1) size check, O(1) inclusion test (IE: Does the category X have code Y in it?), and O(1) mapping back to the original data (code Y is a product with this information).
The other key thing is you really just want to map the connections not all the data. I believe code is probably unique to the product, so that is your key. Your category mapping structure should only concern itself with the minimal amount of unique data (this will increase performance by a lot as well).
Keep in mind, if you have access to an actual database that is probably the more ideal solution, 95% or so of the time once you start wanting to do more complex queries. I would say you almost certainly should be using one, there's probably a database that will suit your needs.
That being said, what you need is this if you don't need to go too far with your queries. It looks like you need to answer these three questions:
Given the code, what is the record (sample data)? This is just a simple code:product object. IE: {25754: {code: ..., price: ..., stock: ..., ...}, {20212: {code: ..., price: ..., stock: ..., ...}}
Given a category, what are the codes in that category? In this case you have a category_id:set(codes) lookup. Very important that you add codes to a set and not a list/array. Sets have O(1) to add/delete/inclusion, while lists/arrays have O(1) add, O(N) delete and O(N) inclusion check.
Given a category, how many are in that category? This is just a data[category].size check (length instead of size in some languages).
Main thing is to use dictionaries and sets for performance.
Time to build the lookups is likely O(P) where P is the total number products. Performance for the queries should be O(1) for each one you need to do.
To avoid O(N^2) performance the lookup should only be calculated once. Should you need to add/remove products from categories, you should adjust the lookup itself and not rebuild it every time. This may mean storing it in a database, building when you first run the app and keeping it in memory, or if the # of products isn't too much, building it at each request (by only using the minimal amount of data to build it, it may be more practical). Generally speaking, even with 1000 products, it should take probably milliseconds to build the category lookup and iterate over them.
Basically your category code should look like his after you've written out the methods.
...
category_lookup = build_category_lookup() # O(P)
product_lookup = build_product_lookup() # O(P)
...
products_for_category = product_lookup[category_id] # O(1)
products_count = products_for_category.length # O(1) | C: sizeof(products_for_category)
...
(Mostly code in ruby these days, so snake_case)

Is there a functional form of a function like foreach over an array that yields all pairs in Javascript

Sorry about the convoluted title, but I hope the following description makes this clearer.
I am currently learning the joys of functional programming in Javascript, using Ramda as my functional library of choice. I have an array which I would like to iterate over in a manner similar way to foreach. However, I would like my anonymous function to be passed all possible pairs from the original array. So in effect, a matrix is formed where by each axis of the matrix to be represented by the contents of the array:
if I have an array with ["a", "b", "c"] then there are in total 9 combinations of pairs; if I take away each element being paired with itself (which could be implemented by a filter, I guess), there are just 6. But if reduce this again, by not getting called back for the reverse pairs, there are just 3.
So my function would be passed back the following pairs:
"a", "b"
"a", "c"
"b", "c"
Is there a functional form of this in Ramda or anything other functional library that can do this? It is generic functionality, but I don't know what the 'name' of this functionality would be; perhaps forEachYieldUniquePair. I would like to know of an idiomatic way to do this before I implement it myself, thanks.
Thanks to Yury for this correct answer:
arr.reduce((acc, letter, index, all) => acc.concat(all.slice(index + 1).map(x => [letter, x])), [])

Fundamental JSON-like object structure?

How to store data correctly in a JSON-like object? From what I've seen, there are two ways to store data inside a json object. Both have different ways to access the data (examples in Python):
Option 1:
obj1 = [
{"id": 1, "payload": "a"},
{"id": 2, "payload": "b"},
{"id": 3, "payload": "c"},
]
Access a certain id's payload in option 1:
for element in obj1:
if element["id"] == 2:
print(element["payload"])
This means, the whole list of elements has to be scanned (possibly) to find the right id and return its value.
On the other hand theres Option 2:
obj2 = {
1: "a",
2: "b",
3: "c",
}
To access the payload of the second "id" is just:
print(obj2[2])
My question now is, why is it more common to see option 1, even though that one seems more complicated to search through? When would I use option 1 and when option 2?
We should clarify some terminology.
When you put a list of values in [], you are creating an array; it is keyed by the array index, not by any element of the data.
When you put a list of keys and values in {}, you are creating an object; you can, as you note, locate a value if you know the corresponding key.
There are many differences between the two structures. In the particular use case you site - wanting to find a data instance based on one of its field's values - an object that uses that field as the key makes sense.
But object keys are unordered. And arrays lend themselves more naturally to having you iterate over all their elements.
It depends what you're going to do with the values; that's why there isn't just one data structure.
Apart from technical artifacts that somehow evolved, option one makes sense in case the order of elements is important.

Separating elements in an Array JavaScript

I have an array that is generated based on user clicks from various questions and alerts like this:
Team A, Player 1, Yellow, C1
This kind of array is created every time an event happens (in a football match). After the match is complete I want to take each of these events and put them into my database. I would like to know how I can separate each part of the array with a ; so that the array that will be exploded will look something like this:
Team A, Player 1, Yellow, C1; Team B, Player 5, Red, S6
I have no problem creating the first array and just need to know how to add in the ; I am wondering if this perhaps becomes an array within an array?
Thank-you in advance
Maybe the following solves your problem (as long as I understand it correctly):
var array = ["Team A", "Player 1", "Yellow", "C1",
"Team B", "Player 5", "Red", "S6"];
var result = "";
for ( var i = 0; i < array.length; i += 4) {
result += array.slice(i, i+4).join(",");
if ( i+4 < array.length ) result += ";";
}
console.log(result);
// prints: Team A,Player 1,Yellow,C1;Team B,Player 5,Red,S6;
Later you can reverse this operation using split:
var array2 = result.split(/,|;/);
// array == array2
Assuming I understand your issue:
I think a 2 dimensional array would be the easiest way to achieve what you are after. You could also look at creating objects and placing those objects into an array. It appears as though you are doing this but I am not entirely sure as your example is not very informative.
It would be helpful to see your code to know how the array is being created, but your last statement is probably on the right track. It sounds like you need either an associative array, or better yet, a collection of some sort. What does this data represent?
Player 1 from Team A received a Yellow card? What is C1? If you can post some code and explain what it is that you're trying to capture it would be more helpful.
From your question I guess that you are using strings, not actual arrays.
Consider using array of objects, because event is a single entity, not a list of entities:
[{team:"Team A", player:"Player 1", type:"Yellow", code:"C1"},
{team:"Team B", player:"Player 5", type:"Red", code:"S6"}]
Code to add an event to array of objects:
function addEvent(events, team, player, type, code) {
events.push({team:team, player:player, type:type, code:code});
}
If you are required to store individual events as arrays:
[["Team A", "Player 1", "Yellow", "C1"],
["Team B", "Player 5","Red", "S6"]]
You can use this code to add an event to 'array of arrays':
function addEvent(events, team, player, type, code) {
events.push([team, player, type, code]);
}
You should ideally push these strings into an array and then push them to an array that includes all the other arrays (2 dimensional array) :
Example: http://jsbin.com/ecoput/2/edit
var data = [["Team A","Player 1","Yellow","C1"],["Team B","Player 5","Red","S6"]]
After this, you should join the array.
data.join(";");
This will result in:
"Team A,Player 1,Yellow,C1;Team B,Player 5,Red,S6"

JavaScript switch case: anyway to force the order of the elements as they are written out?

I've got results being returned to a Google Mapping application in the div sidebar. The results are names of businesses that belong to categories that the client wants returned in a certain order. And unfortunately it's not a straight alpha sort. So one category begins with F and the second one with a C and the last three are A's, for example.
So I need my switch, which works, but naturally insists on dropping the values in alpha sorted (as they are returned from the DB that way) order as that's how it encounters them. What's the best way to set this up so I can grab my preferred categories with their associated company names in the arbitrary order the client has asked for?
Thanks!
Can you iterate over the categories in the order you want them in, and find the object to which it is associated?
E.g. (pseudocode)
var categories = [ 'F', 'C', 'A1', 'A2', 'A3' ].map(function (category) {
return businesses.filter(function (business) {
return business.category === category;
});
});
So the missing step in the answer given here was HOW the map would be implemented and HOW the JS snippet could be implemented. Anyway, I ended up having to ask that as a separate question and finally got a nice working example for an answer.
Russ wrote:
The code given looks most likely to be
using the jQuery JavaScript library
that has some useful functions such as
map() for manipulating arrays.
If we go back to the original problem,
you need to order a list of categories
based on the client's preference.
Let's create a an object literal to
map the ordering
var map = {
F : 5,
C : 3,
A1 : 1,
A2 : 4,
A3 : 2
}
We can use this map to order the array
using the sort method
var array = ['F', 'C', 'A1', 'A2', 'A3'];
array.sort(function(a,b) {
return map[a] - map[b];
});
This returns us ["A1", "A3", "C", "A2", "F"]
Anyway, I wanted to make sure this was included on this thread for anyone searching for this issue in the future or anyone following along right now. Thanks for everyone's input!

Categories

Resources