It's noob question, sorry...
I would like to know if possible to do something like this :
enum animals {CAT, DOG}
mapping(animals => int8) maps;
constructor() {
maps[animals.CAT] = 10;
}
function decrementAnimal(string memory _animal) public {
maps[animals._animal] -= 1;
}
I have this error :
Member "_animal" not found or not visible after argument-dependent lookup in type(enum Test.animals).
I can do something like this :
enum animals {CAT, DOG}
mapping(animals => int8) maps;
constructor() {
maps[animals.CAT] = 10;
maps[animals.DOG] = 10;
}
function decrementCat() public {
maps[animals.CAT] -= 1;
}
function decrementDog() public {
maps[animals.DOG] -= 1;
}
but it seems not optimised....
Thanks all for your replies,
I believe what you are trying to do is the following:
enum Animal {CAT, DOG}
mapping(Animal => int8) maps;
constructor() {
maps[Animal.CAT] = 10;
}
function decrementAnimal(Animal _animal) public {
maps[_animal] -= 1;
}
You can simply pass the enum type as the parameter of the function you are trying to call.
Related
From looking at the code below can anyone show me how you'd write a for loop to get all the values in the mapping? Thanks in advance for the help.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract IterableMapping {
mapping(address => uint) public balances;
mapping(address => bool) public inserted;
address[] public keys;
function set(address _addr, uint _bal) external {
balances[_addr] = _bal;
if (!inserted[_addr]) {
inserted[_addr] = true;
keys.push(_addr);
}
}
function get(uint _index) external view returns (uint) {
address key = keys[_index];
return balances[key];
}
function first() external view returns (uint) {
return balances[keys[0]];
}
function last() external view returns (uint) {
return balances[keys[keys.length - 1]];
}
```
oh i see my mistake now with trying to get the bool values. it would be...
function getAllBools() public view returns (bool[] memory) {
bool[] memory result = new bool[](keys.length);
for (uint i = 0; i < keys.length; i++) {
result[i] = inserted[keys[i]];
}
return result;
}
You can loop through balances by using address as key , hereby you will get All the values in the balances Mapping.
function getAllBalances() public view returns (uint[] memory){
uint[] memory result = new uint[](keys.length);
for (uint i = 0; i < keys.length; i++) {
result[i] = balances[keys[i]];
}
return result;
}
Likewise you can also get values of the inserted mapping
I'm showing an array with items of type 'request' in a table. I want to sort the columns of the table so I planned to make a click method for every column header. This methods sorts the array based on the value of the property shown in that column.
public sortProduct(): void {
this.requests.sort((a, b) => {
if (a.productName < b.productName)
return -1;
if (a.productName > b.productName)
return 1;
return 0;
});
if (!this.productSortOrder) {
this.requests.reverse();
this.productSortOrder = true;
} else {
this.productSortOrder = false;
}
}
This works, but now I need to make a method for every column. I am looking for a way to call a sort method like this:
this.requests.sortMethod(property, order);
This method would then sort the requests array based on the property of the objects in the array and in the given sortorder.
How can I do that? I guess I'm looking for something like Func<> in C#.
You can us a function signature for a similar effect to Func
sortProduct<T>(prop: (c: Product) => T, order: "ASC" | "DESC"): void {
this.requests.sort((a, b) => {
if (prop(a) < prop(b))
return -1;
if (prop(a) > prop(b))
return 1;
return 0;
});
if (order === "DESC") {
this.requests.reverse();
this.productSortOrder = true;
} else {
this.productSortOrder = false;
}
}
// Usage
sortProduct(p=> p.productName, "ASC");
Or you can use the property name instead (keyof Product will ensure the string must be a property of Product):
sortProduct<T>(propName: keyof Product, order: "ASC" | "DESC"): void {
this.requests.sort((a, b) => {
if (a[propName] < b[propName])
return -1;
if (a[propName] > b[propName])
return 1;
return 0;
});
...
}
// Usage
sortProduct("productName", "ASC");
sortProduct("productName_", "ASC"); // Error
You can use a SortUtil class with a static template method sortByProperty:
export class SortUtil {
static sortByProperty<T>(array: T[], propName: keyof T, order: 'ASC' | 'DESC'): void {
array.sort((a, b) => {
if (a[propName] < b[propName]) {
return -1;
}
if (a[propName] > b[propName]) {
return 1;
}
return 0;
});
if (order === 'DESC') {
array.reverse();
}
}
}
I am trying to build a lightweight event system using union types, where I can listen for events from one type in the union. Here is what I have so far (unfortunately, it does not really utilize the types):
class EventSystem {
events: { [key: string]: { (event: EventType) }[] };
constructor() {
this.events = {};
}
emit(key: string, event: EventType): void {
var arr = this.events[key];
for (let i = 0; i < arr.length; ++i) {
arr[i](event);
}
}
on(key: string, callback: (event: EventType) => void) {
if (key in this.events) {
this.events[key].push(callback);
} else {
this.events[key] = [callback];
}
}
}
interface EventA {
foo: Number
}
interface EventB {
bar: Number
baz: string
}
type EventType = EventA | EventB
const EventNames = {
EventA: 'EventA',
EventB: 'EventB'
}
let x = {foo: 2} as EventA;
let y = {
bar: 4,
baz: "test"
} as EventB;
let es = new EventSystem();
es.on(EventNames.EventA, function (a: EventA) {
console.log(a);
});
//Triggers the on above
es.emit(EventNames.EventA, x);
//Unfortunately, this also triggers the on above
es.emit(EventNames.EventA, y);
What I really want is something like this:
let es = new EventSystem<EventType>();
es.on<EventA>(function (a) {
//a is inferred to be EventA
console.log(a);
});
//Triggers the on above
es.emit(x);
//Will not trigger the on, since the type does not match
es.emit(y);
//Type error, since number is not in EventType
es.emit(4);
Is something like this possible in Typescript? If not, is there a more typesafe approach than what I am doing? Or a better way in general to get this type of behavior?
Edit:
For now, I am doing the following. It adds a lot of boilerplate to the EventSystem class (I have hundreds of message types), and also makes the api a little ugly in my opinion, but at least I get type safety. The amount of duplicated code makes me think there must be a better way.
class EventSystem {
events: {[P in EventNames]: { (event: EventType) }[]} = {
'EventA': [],
'EventB': []
};
emitEventA(event: EventA): void {
this.events['EventA'].forEach((eventFunc) => eventFunc(event));
}
emitEventB(event: EventB): void {
this.events['EventB'].forEach((eventFunc) => eventFunc(event));
}
onEventA(callback: (event: EventA) => void) {
this.events['EventA'].push(callback);
}
onEventB(callback: (event: EventB) => void) {
this.events['EventB'].push(callback);
}
}
interface EventA {
foo: Number
}
interface EventB {
bar: Number
baz: string
}
type EventType = EventA | EventB
type EventNames = 'EventA' | 'EventB'
let x = { foo: 2 } as EventA;
let y = {
bar: 4,
baz: "test"
} as EventB;
let es = new EventSystem();
es.onEventA(function (a) {
console.log(a);
});
//Triggers the on above
es.emitEventA(x);
//Correctly caught now
es.emitEventA(y);
Yes, it is possible. Here is some example code that works in my project:
class ProducerClass {
private config;
private logger;
constructor(config: Config, logger: Logger);
enqueue<T extends string, M extends object>(topic: T, message: M): Promise<boolean>;
connect(): void;
}
const producer = ProducerClass(config, logger);
type Topic = 'someTask' | 'someOtherTask';
interface Message {
objectId: number;
}
await producer.enqueue<Topic, Message>('someTask', { objectId: id });
public class PokerHand
{
// ArrayList for cards
private ArrayList<Card> cards;
/**
* Constructor for class Pokerhand
*/
public PokerHand()
{
cards = new ArrayList<Card>(); // arrayList of cards
}
/**
* Add cards to list
*/
public void addCard(Card card1, Card card2, Card card3)
{
cards.add(card1);
cards.add(card2);
cards.add(card3);
}
}
This is my Card Class
public class Card()
{
private int value;
private int suit;
private static String[] suits = { "hearts", "spades", "diamonds", "clubs" };
private static String[] values = { "Ace", "2", "3", "4", "5", "6", "7",
"8", "9", "10", "Jack", "Queen", "King" };
public static String valueAsString( int value ) {
return values[value];
}
Card(int suit, int rank)
{
this.value=value;
this.suit=suit;
}
public String toString()
{
return values[value] + " of " + suits[suit];
}
public int getValue() {
return value;
}
public int getSuit() {
return suit;
}
}
How can I deal a 1000 three card hands? I am stuck on how a variety of things, including what additional methods I need. How can I construct a deal method and how can I make the deal method dish out a thousand random hands while shuffling every time a hand is dealt?
All of these are implementations are based on code from my card library.
Shuffle
public Card[] shuffle(Card[] deck) {
Random gen = new Random();
boolean[] added = new boolean[deck.length];
int positionToAdd = gen.nextInt(deck.length);
Card[] newDeck = new Card[deck.length];
for (int i = 0; i < deck.length; i++) {
while (newDeck[i] == null) {
if (!added[positionToAdd]) {
newDeck[i] = deck[positionToAdd];
positionToAdd = gen.nextInt(deck.length);
added[i] = true;
} else {
positionToAdd = gen.nextInt(deck.length);
}
}
}
return newDeck;
}
Implementation
ArrayList<Card> dealFrom = new ArrayList<Card>();
PokerHand[] hands = new PokerHand[1000];
/*Populate the "dealFrom" yourself here*/
dealFrom = Array.asList(shuffle(dealFrom.toArray()));
for (int i = 0; i < 3000; i += 3) {
//Write your deal method here
hands[i] = new PokerHand(dealFrom[i], dealFrom[i + 1], dealFrom[i + 2]);
}
Hope this helps.
I have a collection(people) that has a many-to-many reference to another collection(dogs). Suspend your disbelief on how there can be more than one people per dog. People just contains member which is an List<Dog>
I would like to select all the people where the people have a certain property(specified in an IList) and pets have a certain property(specified in an IList).
E.g. I have an IList (used for this query only) with the dog’s property value.
public enum EnumLikesToBite
{
No,
Yes,
Sometimes
}
IList <<EnumLikesToBite>> listDogsMayBite =
{ { EnumLikesToBite.Yes},
{ EnumLikesToBite.Sometimes}};
Then another list for the peoples property:
public enum EnumKeepsPetWith
{
Chain,
String,
Rubberband
}
IList <EnumKeepsPetWith> listPeopleWhoDontRestrainDog =
{ { EnumKeepsPetWith.String },
{ EnumKeepsPetWith.Rubberband}};
How can I query out all the people who have a dog that may bite and don’t restrain dog.
Like this pseudo code:
Var result = from p in People where p.KeepsPet in listPeopleWhoDontRestrainDog and dog.LikesToBite in listDogsMayBite.
Result has all the people. Of course if I could get all the dogs who may bite under those people that would be great.
List<int> mayBite = new List<int>()
{
(int) EnumLikesToBite.Yes,
(int) EnumLikesToBite.Maybe
}
List<int> poorRestraint = new List<int>()
{
(int) EnumKeepsPetWith.String,
(int) EnumKeepsPetWith.RubberBand
}
IQueryable<Person> query =
from p in db.People
where poorRestraint.Contains(p.KeepsPetWith)
where p.DogPeople.Any(dp => mayBite.Contains(dp.Dog.DoesBite))
select p;
var query =
from p in db.People
where poorRestraint.Contains(p.KeepsPetWith)
let bitingDogs =
from dp in p.DogPeople
let d = dp.Dog
where mayBite.Contains(d.DoesBite)
where bitingDogs.Any()
select new {Person = p, BitingDogs = bitingDogs.ToList()};
Maybe this code will help.. One of the possible solution are:
var result =
peoples.Where(y => dontRestrainDog.Contains(y.KeepsPetWith) && y.Dogs.Any(x => dogsMayBite.Contains(x.LikesToBite))).ToList();
result.ForEach(y => y.Dogs = y.Dogs.Where(x => dogsMayBite.Contains(x.LikesToBite)).ToList());
which you can see an example of here:
class Program
{
static void Main(string[] args)
{
IList<EnumLikesToBite> dogsMayBite = new List<EnumLikesToBite>
{
{ EnumLikesToBite.Yes }, { EnumLikesToBite.Sometimes }
};
IList<EnumKeepsPetWith> dontRestrainDog = new List<EnumKeepsPetWith>
{
{ EnumKeepsPetWith.String }, { EnumKeepsPetWith.Rubberband }
};
var peoples = new List<People>();
var dogs = new List<Dog>();
Random gen = new Random(2);
for(int i = 0; i < 10; i++)
{
People p = new People
{
PeopleId = i,
KeepsPetWith = (EnumKeepsPetWith) (gen.Next(10)%3),
Dogs = new List<Dog>()
};
Dog d = new Dog
{
DogId = i,
LikesToBite = (EnumLikesToBite) (gen.Next(10)%3),
Peoples = new List<People>()
};
peoples.Add(p);
dogs.Add(d);
}
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; j++)
{
if (gen.Next(10)>7)
{
peoples[i].Dogs.Add(dogs[j]);
}
if (gen.Next(10)>7)
{
dogs[i].Peoples.Add(peoples[j]);
}
}
}
PrintDogs(dogs);
PrintPeoples(peoples);
var result =
peoples.Where(y => dontRestrainDog.Contains(y.KeepsPetWith) && y.Dogs.Any(x => dogsMayBite.Contains(x.LikesToBite))).ToList();
result.ForEach(y => y.Dogs = y.Dogs.Where(x => dogsMayBite.Contains(x.LikesToBite)).ToList());
Console.WriteLine("===================");
PrintPeoples(result);
Console.ReadLine();
}
private static void PrintPeoples(List<People> peoples)
{
Console.WriteLine("=Peoples=");
foreach (var people in peoples)
{
Console.WriteLine("Id: {0}", people.PeopleId);
Console.WriteLine("KeepsPetWith: {0}", people.KeepsPetWith);
Console.WriteLine("Dogs: ");
foreach (var dog in people.Dogs)
{
Console.Write("{0}, ", dog.DogId);
}
Console.WriteLine();
}
}
private static void PrintDogs(List<Dog> dogs)
{
Console.WriteLine("=Dogs=");
foreach (var dog in dogs)
{
Console.WriteLine("Id: {0}", dog.DogId);
Console.WriteLine("LikesToBite: {0}", dog.LikesToBite);
Console.WriteLine("Peoples: ");
foreach (var people in dog.Peoples)
{
Console.Write("{0}, ", people.PeopleId);
}
Console.WriteLine();
}
}
}
public class People
{
public int PeopleId { get; set; }
public EnumKeepsPetWith KeepsPetWith { get; set; }
public IList<Dog> Dogs { get; set; }
}
public class Dog
{
public int DogId { get; set; }
public EnumLikesToBite LikesToBite { get; set; }
public IList<People> Peoples { get; set; }
}
public enum EnumLikesToBite
{
No,
Yes,
Sometimes
}
public enum EnumKeepsPetWith
{
Chain,
String,
Rubberband
}