Iterable Mapping- how to retreive all the values with For-Loop? - for-loop

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

Related

How to map enum => int solidity

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.

Need My Solidity Contract Reviewed, the original code had arguments, but I don't know how to input that in nor what they mean

How do I add in the arguments and set the baseURI?
It is mainly having issues identifying totalsupply and baseuri.
input the below
name (string): Test MB
symbol (string): TEST
maxNftSupply (uint256): 10000
saleStart (uint256): 1619060439?
Where would I put this, there is also an encoded view after verification on etherscan, is that something I need to add?
contract TestMB is ERC721, Ownable {
using SafeMath for uint256;
string public TEST_PROVENANCE = "";
uint256 public startingIndexBlock;
uint256 public startingIndex;
uint256 public constant testPrice = 80000000000000000; //0.08 ETH
uint public constant maxTestPurchase = 20;
uint256 public MAX_TEST;
bool public saleIsActive = false;
uint256 public REVEAL_TIMESTAMP;
constructor(string memory name, string memory symbol, uint256 maxNftSupply, uint256 saleStart) ERC721(name, symbol) {
MAX_TEST = maxNftSupply;
REVEAL_TIMESTAMP = saleStart + (9900 * 9);
}
function withdraw() public onlyOwner {
uint balance = address(this).balance;
msg.sender.transfer(balance);
}
function reserveTest() public onlyOwner {
uint supply = totalSupply();
uint i;
for (i = 0; i < 100; i++) {
_safeMint(msg.sender, supply + i);
}
}
function setRevealTimestamp(uint256 revealTimeStamp) public onlyOwner {
REVEAL_TIMESTAMP = revealTimeStamp;
}
function setProvenanceHash(string memory provenanceHash) public onlyOwner {
TEST_PROVENANCE = provenanceHash;
}
function setBaseURI(string memory baseURI) public onlyOwner {
_setBaseURI(baseURI);
}
function flipSaleState() public onlyOwner {
saleIsActive = !saleIsActive;
}
function mintTest(uint numberOfTokens) public payable {
require(saleIsActive, "Sale must be active to mint Test");
require(numberOfTokens <= maxTestPurchase, "Can only mint 20 tokens at a time");
require(totalSupply().add(numberOfTokens) <= MAX_TEST, "Purchase would exceed max supply of Test");
require(testPrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");
for(uint i = 0; i < numberOfTokens; i++) {
uint mintIndex = totalSupply();
if (totalSupply() < MAX_TEST) {
_safeMint(msg.sender, mintIndex);
}
}
if (startingIndexBlock == 0 && (totalSupply() == MAX_TEST || block.timestamp >= REVEAL_TIMESTAMP)) {
startingIndexBlock = block.number;
}
}
function setStartingIndex() public {
require(startingIndex == 0, "Starting index is already set");
require(startingIndexBlock != 0, "Starting index block must be set");
startingIndex = uint(blockhash(startingIndexBlock)) % MAX_TEST;
// Just a sanity case in the worst case if this function is called late (EVM only stores last 256 block hashes)
if (block.number.sub(startingIndexBlock) > 255) {
startingIndex = uint(blockhash(block.number - 1)) % MAX_TEST;
}
// Prevent default sequence
if (startingIndex == 0) {
startingIndex = startingIndex.add(1);
}
}
function emergencySetStartingIndexBlock() public onlyOwner {
require(startingIndex == 0, "Starting index is already set");
startingIndexBlock = block.number;
}
}
If you are the deployer of the contract so you will be the contract owner. Then you will be able to call onlyOwner functions.
To set baseURI, you have to call setBaseURI function with parameter of your base url.
You have to verify your contract source code on etherscan to call functions.
If you don't know how to verify your contract code, then you can deploy your contract through Remix and then you will be able to call contract functions.
I hope i got the problem and this is the answer.

Sort array of objects based on property in typescript

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();
}
}
}

Partition/split/section IEnumerable<T> into IEnumerable<IEnumerable<T>> based on a function using LINQ?

I'd like to split a sequence in C# to a sequence of sequences using LINQ. I've done some investigation, and the closest SO article I've found that is slightly related is this.
However, this question only asks how to partition the original sequence based upon a constant value. I would like to partition my sequence based on an operation.
Specifically, I have a list of objects which contain a decimal property.
public class ExampleClass
{
public decimal TheValue { get; set; }
}
Let's say I have a sequence of ExampleClass, and the corresponding sequence of values of TheValue is:
{0,1,2,3,1,1,4,6,7,0,1,0,2,3,5,7,6,5,4,3,2,1}
I'd like to partition the original sequence into an IEnumerable<IEnumerable<ExampleClass>> with values of TheValue resembling:
{{0,1,2,3}, {1,1,4,6,7}, {0,1}, {0,2,3,5,7}, {6,5,4,3,2,1}}
I'm just lost on how this would be implemented. SO, can you help?
I have a seriously ugly solution right now, but have a "feeling" that LINQ will increase the elegance of my code.
Okay, I think we can do this...
public static IEnumerable<IEnumerable<TElement>>
PartitionMontonically<TElement, TKey>
(this IEnumerable<TElement> source,
Func<TElement, TKey> selector)
{
// TODO: Argument validation and custom comparisons
Comparer<TKey> keyComparer = Comparer<TKey>.Default;
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
{
yield break;
}
TKey currentKey = selector(iterator.Current);
List<TElement> currentList = new List<TElement> { iterator.Current };
int sign = 0;
while (iterator.MoveNext())
{
TElement element = iterator.Current;
TKey key = selector(element);
int nextSign = Math.Sign(keyComparer.Compare(currentKey, key));
// Haven't decided a direction yet
if (sign == 0)
{
sign = nextSign;
currentList.Add(element);
}
// Same direction or no change
else if (sign == nextSign || nextSign == 0)
{
currentList.Add(element);
}
else // Change in direction: yield current list and start a new one
{
yield return currentList;
currentList = new List<TElement> { element };
sign = 0;
}
currentKey = key;
}
yield return currentList;
}
}
Completely untested, but I think it might work...
alternatively with linq operators and some abuse of .net closures by reference.
public static IEnumerable<IEnumerable<T>> Monotonic<T>(this IEnumerable<T> enumerable)
{
var comparator = Comparer<T>.Default;
int i = 0;
T last = default(T);
return enumerable.GroupBy((value) => { i = comparator.Compare(value, last) > 0 ? i : i+1; last = value; return i; }).Select((group) => group.Select((_) => _));
}
Taken from some random utility code for partitioning IEnumerable's into a makeshift table for logging. If I recall properly, the odd ending Select is to prevent ambiguity when the input is an enumeration of strings.
Here's a custom LINQ operator which splits a sequence according to just about any criteria. Its parameters are:
xs: the input element sequence.
func: a function which accepts the "current" input element and a state object, and returns as a tuple:
a bool stating whether the input sequence should be split before the "current" element; and
a state object which will be passed to the next invocation of func.
initialState: the state object that gets passed to func on its first invocation.
Here it is, along with a helper class (required because yield return apparently cannot be nested):
public static IEnumerable<IEnumerable<T>> Split<T, TState>(
this IEnumerable<T> xs,
Func<T, TState, Tuple<bool, TState>> func,
TState initialState)
{
using (var splitter = new Splitter<T, TState>(xs, func, initialState))
{
while (splitter.HasNext)
{
yield return splitter.GetNext();
}
}
}
internal sealed class Splitter<T, TState> : IDisposable
{
public Splitter(IEnumerable<T> xs,
Func<T, TState, Tuple<bool, TState>> func,
TState initialState)
{
this.xs = xs.GetEnumerator();
this.func = func;
this.state = initialState;
this.hasNext = this.xs.MoveNext();
}
private readonly IEnumerator<T> xs;
private readonly Func<T, TState, Tuple<bool, TState>> func;
private bool hasNext;
private TState state;
public bool HasNext { get { return hasNext; } }
public IEnumerable<T> GetNext()
{
while (hasNext)
{
Tuple<bool, TState> decision = func(xs.Current, state);
state = decision.Item2;
if (decision.Item1) yield break;
yield return xs.Current;
hasNext = xs.MoveNext();
}
}
public void Dispose() { xs.Dispose(); }
}
Note: Here are some of the design decisions that went into the Split method:
It should make only a single pass over the sequence.
State is made explicit so that it's possible to keep side effects out of func.

Saving a custom object using IsloatedStorageSettings

I'm trying to save an object in IsolatedStorageSettings to save the high scores for my game, but whenever I try to save an updated copy of the object C# seems to think the object hasn't changed. I tried creating a custom Equals function for the HighScores class but that doesn't seem to help.
Any idea what I'm doing wrong?
Thanks
public bool AddOrUpdateValue(string Key, Object value)
{
bool valueChanged = false;
// If the key exists
if (isolatedStore.Contains(Key))
{
// If the value has changed
if (isolatedStore[Key] != value) //This keeps returning false
{
// Store the new value
isolatedStore[Key] = value;
valueChanged = true;
}
}
// Otherwise create the key.
else
{
isolatedStore.Add(Key, value);
valueChanged = true;
}
return valueChanged;
}
//This is located inside the HighScores class
public bool Equals(HighScores newHighScores)
{
for (int i = 0; i < highScores.Length; i++)
{
if (!highScores[i].Name.Equals(newHighScores.GetIndex(i).Name))
{
return false;
}
if (!highScores[i].Time.Equals(newHighScores.GetIndex(i).Time))
{
return false;
}
}
return true;
}
You haven't implemented the equality operators '==' and '!=' and these compare reference equality, you are going to have provide the implementation which maps on to your 'Equals' method
http://msdn.microsoft.com/en-us/library/ms173147%28v=vs.80%29.aspx
You should do isolatedStore.Save() to commit the changes

Resources