我有一点复杂的字典。
这是一本包含两种枚举类型的字典。列表<>
\r
因此,当我想使用它时,我会这样做:
Dictionary<BiomeType, Dictionary<LocationType, List<string>>> myDictionary;
当我尝试将“myString”添加到myList时,它会抛出一个明显的&amp;可预见的错误:“KeyNotFoundException:字典中没有给定的密钥。”
C#中是否有任何方法可以自动让Dictionary添加Key(如果还没有)?我有很多BiomeTypes&amp;甚至更多的LocationTypes。 PITA必须创建每个List,然后创建每个locationtype字典,然后为每个BiomeType添加它。所有这些只是为了初始化这个复杂的字典。有没有简单的方法可以做到这一点?
我正在将它用于gamedev,将对象存储在Dictionary中,所以我可以通过执行类似
的操作来访问它们//Add "myString" to the List<string>
myDictionary[BiomeType.Jungle][LocationType.City1].Add("myString"));
答案 0 :(得分:1)
也许,你可以试试这个:
import React from 'react';
import ReactDom from 'react-dom';
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import { Router, Route, IndexRoute, hashHistory } from 'react-router';
import { syncHistoryWithStore, routerReducer } from 'react-router-redux';
import thunkMiddleware from 'redux-thunk';
import reducers from './redux/reducers';
import Entrance from './components/Entrance.jsx';
import EntranceNone from './components/EntranceNone.jsx';
import CreditPoints from './components/CreditPoints.jsx';
import CreditPrivilege from './components/CreditPrivilege.jsx';
import CreditPromote from './components/CreditPromote.jsx';
let reduxDevTool = null;
let combReducer = { app: reducers, routing: routerReducer };
let store = createStore(combineReducers(combReducer), applyMiddleware(thunkMiddleware));
const history = syncHistoryWithStore(hashHistory, store);
ReactDom.render(
<Provider store={store}>
<div>
<Router history={history}>
<Route path="/" component={ Entrance }></Route>
<Route path="/EntranceNone" component={ EntranceNone }></Route>
<Route path="/creditPoints" component={ CreditPoints }></Route>
<Route path="/privilege" component={ CreditPrivilege }></Route>
<Route path="/promote" component={ CreditPromote }></Route>
</Router>
</div>
</Provider>,
document.getElementById('app')
);
require('../less/entrance.css');
import { initRootFontSize,originDomin } from '../utils';
import React,{Component} from 'react';
import classNames from 'classnames';
import 'babel-polyfill';
import cookie from 'react-cookie';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as Actions from '../redux/action';
import { hashHistory ,Link } from 'react-router';
class Entrance extends Component {
constructor (props) {
super(props);
initRootFontSize();
this.state = {
agree:true,
submitFlag:false
};
}
handleAgreeMent(){
this.setState({agree:!this.state.agree});
}
componentDidMount(){
if(creditData.isOpenCreditService === "0"){
this.context.router.push('/');
}else{
this.context.router.push('/creditPoints');
}
}
componentDidUpdate(prevProps,prevState){
if(this.props.resCode && this.state.submitFlag){
if(this.props.resCode == "000"){
this.context.router.push('/creditPoints');
}else{
alert(this.props.resMsg);
}
}
}
handleClick(){
if(this.state.agree){
this.props.actions.fetchIsOpen();
this.setState({submitFlag:true});
}
}
render () {
return(
<div className="wrap">
<div className="credit-img"></div>
<div className="credit-cont">
<p className="credit-cont-up">xxx</p>
<p className="credit-cont-down">xxx</p>
</div>
<div className="credit-agree"><span className={classNames({icon: true, iconSelected: this.state.agree})} onClick={this.handleAgreeMent.bind(this)}></span><span className="credit-agree-cont">xx<a href={originDomin()+'static.pay.xiaomi.com/mi-credit-points/src/html/agreeMent.html'} className="credit-agree-detail">xxx</a></span></div>
<div className={classNames({button: true,bottonFalse:this.state.agree,submitFlag:this.state.submitFlag})} onClick={this.handleClick.bind(this)}>{this.state.submitFlag?'x':'xx'}</div>
</div>
);
}
}
function mapStateToProps(state) {
return {
resCode: state.app.resCode,
resMsg: state.app.resMsg,
dataList: state.app.dataList
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
};
}
Entrance.contextTypes = {
router: React.PropTypes.object
};
export default connect(mapStateToProps, mapDispatchToProps)(Entrance);
答案 1 :(得分:1)
你可以这样做(虽然老实说我不确定你应该这样做!)
下面的类是一种类型,通常像字典一样,按照你的要求行事,并进行一些其他更改,以便在每次向索引器询问没有的项目时隐藏它所创建的空白项目。存在。
public class SmellyDictionary<T1, T2>: IDictionary<T1, T2>, ICollection where T2 : ICollection, new()
{
private readonly IDictionary<T1, T2> _dict = new Dictionary<T1, T2>();
public T2 this[T1 key]
{
get
{
T2 value;
if (!_dict.TryGetValue(key, out value))
_dict[key] = value = new T2(); // This stinks!
return value;
}
set { _dict[key] = value; }
}
public bool Contains(KeyValuePair<T1, T2> item)
{
return _dict.Contains(item);
}
public bool ContainsKey(T1 key)
{
return _dict.ContainsKey(key) && _dict[key].Count > 0; // This hides the smell
}
public int Count { get { return _dict.Count(kvp => kvp.Value.Count > 0); } } // This hides the smell
public void Add(T1 key, T2 value)
{
T2 currentValue;
if (_dict.TryGetValue(key, out currentValue) && currentValue.Count > 0)
throw new ArgumentException("A non empty element with the same key already exists in the SmellyDictionary");
_dict[key] = value;
}
public void Add(KeyValuePair<T1, T2> item)
{
Add(item.Key, item.Value);
}
public bool Remove(T1 key)
{
return _dict.Remove(key);
}
public bool Remove(KeyValuePair<T1, T2> item)
{
return _dict.Remove(item);
}
public bool TryGetValue(T1 key, out T2 value)
{
return _dict.TryGetValue(key, out value);
}
public ICollection<T1> Keys { get { return _dict.Keys; } }
public ICollection<T2> Values { get { return _dict.Values; } }
public object SyncRoot { get { return ((ICollection)_dict).SyncRoot; } }
public bool IsSynchronized { get { return ((ICollection)_dict).IsSynchronized; } }
public IEnumerator<KeyValuePair<T1, T2>> GetEnumerator()
{
return _dict.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Clear()
{
_dict.Clear();
}
public void CopyTo(Array array, int index)
{
_dict.CopyTo((KeyValuePair<T1, T2>[])array, index);
}
public void CopyTo(KeyValuePair<T1, T2>[] array, int arrayIndex)
{
_dict.CopyTo(array, arrayIndex);
}
public bool IsReadOnly { get { return _dict.IsReadOnly; } }
}
答案 2 :(得分:1)
这是一个更明智的选择。只需调用此方法即可将字符串添加到字典中。
private void AddCityToDictionary(Dictionary<BiomeType, Dictionary<LocationType, List<string>>> myDictionary, BiomeType biome, LocationType location, string city)
{
Dictionary<LocationType, List<string>> locationDictionary;
if (!myDictionary.TryGetValue(biome, out locationDictionary))
locationDictionary = myDictionary[biome] = new Dictionary<LocationType, List<string>>();
List<string> cityList;
if (!locationDictionary.TryGetValue(location, out cityList))
cityList = locationDictionary[location] = new List<string>();
cityList.Add(city);
}
答案 3 :(得分:0)
简单地循环遍历每个可能的枚举类型&amp;添加新值可以完全填充此多维字典。
Dictionary<BiomeType, Dictionary<LocationType, List<string>>> myDictionary = new Dictionary<BiomeType, Dictionary<LocationType, List<string>>>(); //No thanks to troll users like Peter.
foreach (BiomeType biomeType in System.Enum.GetValues(typeof(BiomeType)))
{
Dictionary<LocationType, List<string>> newLocDict = new Dictionary<LocationType, List<string>>(); //No thanks to troll users like Peter.
foreach (LocationType locType in System.Enum.GetValues(typeof(LocationType)))
{
List<string> newList = new List<string>();
newLocDict.Add(locType, newList); //Add the final bit here & voila! Finished! No thanks to troll users like Peter.
}
myDictionary.Add(biomeType, newLocDict);
}
如果您不想使用ALL枚举值完全填充容器,Robyn的解决方案的工作方式相同。