How can I create a value in java script map to behave like integer counter.
var map = { "cars" : count, "buses" : count };
The way I want to use this map is:
if (car) {
// incremeent the count of cars
} else {
// increment the count of busses
}
My question is how should such a map look like syntactically in javascript ?
You can initialize it like this:
var map = {cars: 0, buses: 0 };
Then, you can increment like this:
if (car) {
++map.cars;
} else {
++map.buses;
}
But, I suspect you need a little more logic to your if (car) so you can actually tell that it is a car type, not just a boolean but you haven't shown us how that part of your code works to know exactly what to suggest.
You could also be a little more object oriented and put the method on the map:
var map = {
cars: 0,
buses: 0,
count: function(obj) {
if (obj) {
++this.cars;
} else {
++this.buses;
}
}
};
map.count(item);
Again, you'll have to modify the if (obj) portion of this to actually discern whether the type is a car or not, but you haven't disclosed enough about your code to know how to do that.
var counts = { cars: 0, buses: 0 };
if (car) {
counts.cars++;
} else {
counts.buses++;
}
// or more succinctly:
counts[car ? 'cars' : 'buses']++;
If you have a parameter, say vehicles, whose value is either cars or buses, then you can do:
map[vehicles]++;
You can also do:
map[car? 'cars' : 'buses']++;
If you show more of what you are doing, more help can be provided on what is likely to be most appropriate.
Related
i'm currently learning JavaScript and have to do this challenge for one of the coding challenges and the challenge is :
"Create an object called 'scorers' which contains the name of the players who scored as properties and the number of goals as the value. in this game it will look like this:
{
Gnarby: 1,
Hummels: 1,
Lewandowski: 2
}"
the solution :
"loop over the array, and add the array elements as object properties,
and then increase the count as we encounter a new occurrence of a certain element"
the object :
const game = {
scored: ['Lewandowski', 'Gnarby', 'Lewandowski', 'Hummels']
};
the solution is :
const scorers = {};
for (const player of game.scored) {
scorers[player] ? scorers[player]++ : (scorers[player] = 1);
}
and the outcome is :
[Lewandowski: 2, Gnarby: 1, Hummels: 1]
i don't understand exactly what happens at the scorers[player] ? scorers[player]++ : (scorers[player] = 1);
what the scorers[player]++ do ?
It's a ternary operator that checks whether game contains the value of player as a property. If so, it increments the value of that property. Otherwise, it sets it to 1.
It can also be rewritten like so:
if(scorers[player]){
scorers[player]++;
} else {
scorers[player] = 1;
}
If scorers does not have the value of player as a property, scorers[player] will return undefined, which, when coerced to a boolean, is false.
I have a snippet of code here where i have an array that may or may not have keys in it. When the user presses on a 'friend' they add them to a list (array) where they might start a chat with them (add 3 friends to the array, then start a chatroom). The users selected might be toggled on or off.
Current Behavior:
i can add/remove one person, but i cant add multiple people to the array at the same time. When i add one person, select another - the first person is 'active', when i remove the first person, the second person automatically becomes active
Expected Behavior:
I would like to be able to add multiple people to the array and then remove any of the selected items from the array
onFriendChatPress = (key) => {
console.log(key) // this is my key 'JFOFK7483JFNRW'
let friendsChat = this.state.friendsChat // this is an empty array initially []
if (friendsChat.length === 0) {
friendsChat.push(key)
} else {
// there are friends/keys in the array loop through all possible items in the array to determine if the key matches any of the keys
for (let i = 0; i < this.state.selGame.friends.length; i++) {
// if the key matches, 'toggle' them out of the array
if (friendsChat[i] === key) {
friendsChat = friendsChat.filter(function (a) { return a !== key })
}
else {
return friendsChat.indexOf(key) === -1 ? friendsChat.push(key) :
}
}
}
}
Help please!
From your code, I was quite confused regarding the difference between this.state.selGame.friends and this.state.friendsChat. Maybe I missed something in your explication. However, I felt that your code seemed a bit too overcomplicated for something relatively simple. Here's my take on that task:
class Game {
state = {
friendsChat: [] as string[],
};
onFriendToggle(key: string) {
const gameRoomMembers = this.state.friendsChat;
if (gameRoomMembers.includes(key)) {
this.state.friendsChat = gameRoomMembers.filter(
(member) => member !== key
);
} else {
this.state.friendsChat = [...gameRoomMembers, key];
}
}
}
I used typescript because it makes things easier to see, but your JS code should probably give you a nice type inference as well. I went for readability over performance, but you can easily optimize the script above once you understand the process.
You should be able to go from what I sent you and tweak it to be according to what you need
I have this algorithme issue, I would like to check if an Object is already present in my Array before adding it.
I tried many different approaches (indexOf, filter...), and my last attempt is with an angular.foreach.
The problem is my $scope.newJoin remains always empty. I understood why, it's because the if is never read, because of the 0 size of my $scope.newJoin, but I don't know how to figure this out...
$scope.newJoinTMP is composed by : 6 Objects, within each a timePosted attribute (used for compare these different array Objects).
$scope.newJoin is an empty Array. I want to fill it with the Objects inside $scope.newJoinTMP but with the certainty to have once each Objects, and not twice the same ($scope.newJoinTMP can have duplicates Objects inside, but $scope.newJoin mustn't).
angular.forEach($scope.newJoinTMP, function(item)
{
angular.forEach($scope.newJoin, function(item2)
{
if (item.timePosted === item2.timePosted)
{
//snap.val().splice(snap.val().pop(item));
console.log("pop");
}
else
{
$scope.newJoin.push(item);
console.log("newJoin :", $scope.newJoin);
}
});
});
if(!$scope.newJoin.find(el=>item.timePosted===el.timePosted){
$scope.newJoin.push(item);
console.log("newJoin :", $scope.newJoin);
}
You dont want to push inside an forEach, as it will push multiple times...
There might be better ways to handle your particular situation but here's a fix for your particular code.
Replaced your inner for each with some which returns boolean for the presence of element and by that boolean value, deciding whether to add element or not
angular.forEach($scope.newJoinTMP, function(item)
{
var isItemPresent = $scope.newJoin.some(function(item2)
{
return item.timePosted === item2.timePosted;
//you dont need this conditional handling for each iteration.
/* if (item.timePosted === item2.timePosted)
{
//snap.val().splice(snap.val().pop(item));
console.log("pop");
}
else
{
$scope.newJoin.push(item);
console.log("newJoin :", $scope.newJoin);
} */
});
if( ! isItemPresent ) {
$scope.newJoin.push(item);
} else {
//do if it was present.
}
});
If you want to avoid the nested loop (forEach, some, indexOf, or whatever) you can use an auxiliar object. It will use more memory but you will spent less time.
let arr = [{ id: 0 }, { id:0 }, { id: 1}];
let aux = {};
const result = arr.reduce((result, el) => {
if (aux[el.id] === undefined) {
aux[el.id] = null;
return [el, ...result];
} else {
return result;
}
}, []);
console.log(result);
You can use reduce
$scope.newJoin = $scope.newJoinTMP.reduce(function(c, o, i) {
var contains = c.some(function(obj) {
return obj.timePosted == o.timePosted;
});
if (!contains) {
c.push(o);
}
return c;
}, []);
The problem with your current code is, if newJoin is empty, nothing will ever get added to it - and if it isnt empty, if the first iteration doesn't match the current item being iterated from newJoinTMP - you're pushing.
I am new in JavaScript, And I am trying to map my controller's buttons and leds for mixxx application. Is that an object, an array? var is missing.
BehringerCMDMM1.leds = [
// Master
{ "shiftButton" : 0x12 },
// Deck 1
{ "sync" : 0x30 },
// Deck 2
{ "sync" : 0x33 }
];
I have an error here,
BehringerCMDMM1.shiftButton = function (channel, control, value, status, group) {
// Note that there is no 'if (value)' here so this executes both when the shift button is pressed and when it is released.
// Therefore, BehringerCMDMM1.shift will only be true while the shift button is held down
var deck = BehringerCMDMM1.groupToDeck(group);
BehringerCMDMM1.shift = !BehringerCMDMM1.shift // '!' inverts the value of a boolean (true/false) variable
BehringerCMDMM1.setLED(BehringerCMDMM1.leds[deck]["shiftButton"], BehringerCMDMM1.shift);
}
about "shiftButton" as undefined.
also I have this function
BehringerCMDMM1.setLED = function(value, status) {
status = status ? 0x7F : 0x00;
midi.sendShortMsg(0x94, value, status);
}
This is from a javascript file I found on the internet created for a different controller. So, I am trying things to understand how can I configure mine.
BehringerCMDMM1.leds is an array of objects. Within that array, the element at index 0 is an object that has a shiftButton property. Thus, the only way to get the 0x12 value in your example is to do this:
BehringerCMDMM1.leds[0]['shiftButton']
So when this code executes...
var deck = BehringerCMDMM1.groupToDeck(group);
...the value of deck is probably something other than 0, and you're accessing one of the sync objects in the BehringerCMDMM1.leds array. For example, if the value of deck was 1, then this...
BehringerCMDMM1.leds[deck]['shiftButton']
...will be undefined because you're effectively doing this:
BehringerCMDMM1.leds[1]['shiftButton']
Ok,
I am new in JavaScript, And I am trying to map my controller's buttons and leds for mixxx application. Is that an object, an array?
You have a array of objects.
var is missing.
You should test what is inside yout deck variable. Try this:
console.log(deck);
if (deck in BehringerCMDMM1.leds) {
BehringerCMDMM1.setLED(BehringerCMDMM1.leds[deck]["shiftButton"], BehringerCMDMM1.shift);
} else {
console.log("Index: "+deck+" doesn't exist");
}
I do not want to use Switch in my code, so I'm looking for some alternative
Example with Switch:
function write(what) {
switch(what) {
case 'Blue':
alert ('Blue');
break;
...
case 'Red':
alert ('Red');
break;
}
}
Example without Switch:
colors = [];
colors['Blue'] = function() { alert('Blue'); };
colors['Red'] = function() { alert('Red'); };
function write(what) {
colors[what]();
}
My questions are:
Do you know any other alternatives?
Is this best solution?
I have only a note about your second approach, you shouldn't use an Array to store non-numeric indexes (that you would call in other languages an associative array).
You should use a simple Object.
Also, you might want to check if the what argument passed to your write function exists as a property of your colors object and see if it's a function, so you can invoke it without having run-time errors:
var colors = {};
colors['Blue'] = function() { alert('Blue'); };
colors['Red'] = function() { alert('Red'); };
function write(what) {
if (typeof colors[what] == 'function') {
colors[what]();
return;
}
// not a function, default case
// ...
}
I used a structure like this today:
var chosenColor = 'red';
var colorString = {
'red': 'The color is red.',
'green': 'The color is green.',
'blue': 'The color is blue.',
}[chosenColor] || 'The color is unknown.';
I like that it's a really small amount of code to choose a string based on choice.
You could also pass it to a function:
alert({
'red': 'The color is red.',
'green': 'The color is green.',
'blue': 'The color is blue.',
}[chosenColor] || 'The color is unknown.');
You could use object literals, and try catch to trap the default:
function write(what) {
var colors = {
'Blue': function(){ alert('Light-Blue'); },
'Red': function(){ alert('Deep-Red'); },
'Green': function(){ alert('Deep-Green'); }
}
try {colors[what]();}
catch(err) {colors['Green']();}//default behaviour
}
write('Pink');
Question 2:
Generally, if you can replace custom control structures with a dictionary lookup, you're perfectly fine. It's easy to read and highly elegant -- stick with it.
I had to do do a compare for a group sort of object props for a list and did not want to do a switch/case for all the possibilities so I did an array of objects assignment to a numeric rank first so the case became a simple compare. This is only 4 possibilities but you get the drift of how to extend this to situation where a switch/case becomes unmanageable:
function mySort2(item1,item2){
var matrix = {
'repair': 4,
'r/r': 3,
'part': 2,
'misc': 1
};
(matrix[item1.category] < matrix[item2.category]) ? return +1 : return -1;
// if possible bad data need to check for this first ???
i1=matrix[item1.category] || null;
i2=matrix[item2.category] || null;
if (i1==null){
// handle bad data in item 1
return +1; // put it after 2
}
if (i2==null){
// ditto
return -1; //put 1 first
}
if (i1<i2)
return +1;
else
return -1;
}
You are pretty much there already. If possible you might want to add a helper function to make the setup easier. For Example:
function setup(what)
{
colors[what] = function() { alert(what); };
}
EDIT:
If what you want to do for each option is more complicated clearly this will not work. As mentioned in the comments by #roe this uses the global colors which is often frowned upon.
Alternatively, you can also use Dictionaries, so you could see the type of the function return, I think it's clean and scalable, although it's just pure JS.
const ColorDictionary = {
red: 'applies red color',
blue: ' applies blue color',
green: 'applies green color',
}
const useShowColors = (color) => {
// color will be selected or fallout to default value.
const getColor = () => (
ColorDicionary[color] ?? 'applies default color'
)
return { getColor }
}
const { getColor } = useShowColors() //pass the color you wish.
An alternative is to define a class with a write method, and override that in subclasses Red and Blue to do the right thing.
Whether or not that is better than your proposed solution, depends on your particular situation.
As I said, it's great. The only thing I can add to your solution is that it's perhaps better to localize your colors.
function write(what) {
var colors = [];
colors['Blue'] = function() { alert('Blue'); };
colors['Red'] = function() { alert('Red'); };
colors[what]();
}