c# - 复制PHP的动态多维数组创建

标签 c# php data-structures

因此,我正在将一个项目从 PHP 转换为 C#。作为查询的结果获得了通用数据列表

//C# code
public class TermsCommodityModel
{
    public int terms_id { get; set; }
    public int commodity_id { get; set; }
    public int custom { get; set; }
    public int calculated { get; set; }
    public string name { get; set; }
    public string formula { get; set; }
    public int division_id { get; set; }
}

我能够将其填充到 termsTable 中这是 List<TermsCommodityModel> .然后 PHP 代码开始循环 termsTable .(C# 和 PHP 代码使用相同的变量以便于转换)。第一行完全改变了我的数据结构

//PHP code
if (!isset($termsTable[$name]))
    $termsTable[$name] = array();

我想,这很奇怪但可行。然后第二个条件创建了另一个子数组并继续。现在 PHP 代码看起来是这样的,

//PHP Code
if (!isset($termsTable[$name][$t->commodity_id]))
    $termsTable[$name][$t->commodity_id] = array();
//.Omitted for brevity
//....
$year = date("Y") + 5;
for ($y = 2008; $y<= $year; $y++) {
    $termsTable[$name][$t->commodity_id][$y] = array();
    for ($i=1; $i<=12; $i++)
        $termsTable[$name][$t->commodity_id][$y][$i] = 0;
}   

这是最终的数据结构

//PHP Code
$termsTable[$name]
$termsTable[$name][$t->commodity_id]
$termsTable[$name][$t->commodity_id][$y]
$termsTable[$name][$t->commodity_id][$y][$i]

这实质上是动态地创建了对象数组的数组的数组。问题是 PHP 是一种动态类型的语言。它不需要指定类型

C# 中的哪个数据结构可以做到这一点?不能使用 tuple因为它们是分层的,对吧?

用什么方法来解决这个问题?任何指示都会非常有帮助,因为这很重要。

最佳答案

我不确定 TermsCommodityModel 与 php 代码有什么关系,因为据我所知,它没有在任何地方显示。无论如何,您可以通过 (ab) 使用 dynamicDynamicObject 来实现类似于 php 的语法。首先像这样创建类:

public class DynamicDictionary : DynamicObject {
    private readonly Dictionary<object, object> _dictionary;

    public DynamicDictionary() {
        _dictionary = new Dictionary<object, object>();
    }

    public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) {
        // this will be called when you do myDict[index] (but not myDict[index] = something)
        if (indexes.Length != 1)
            throw new Exception("Only 1-dimensional indexer is supported");
        var index = indexes[0];
        // if our internal dictionary does not contain this key
        // - add new DynamicDictionary for that key and return that
        if (_dictionary.ContainsKey(index)) {
            _dictionary.Add(index, new DynamicDictionary());
        }
        result = _dictionary[index];
        return true;
    }

    public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value) {
        // this will be called when you do myDict[index] = value
        if (indexes.Length != 1)
            throw new Exception("Only 1-dimensional indexer is supported");
        var index = indexes[0];
        // just set value
        _dictionary[index] = value;
        return true;
    }
}

然后像这样使用它:

dynamic termsTable = new DynamicDictionary();
var name = "name";
int commodityId = 123;
var year = DateTime.Now.Year + 5;
for (int y = 2008; y <= year; y++) {
    for (int i = 1; i < 12; i++) {
        // that's fine
        termsTable[name][commodityId][y][i] = 0;
    }
}

// let's see what we've got:
for (int y = 2008; y <= year; y++) {
    for (int i = 1; i < 12; i++) {
        // that's fine
        Console.WriteLine(termsTable[name][commodityId][y][i]);
    }
}

要进一步反射(reflect)您的 php 代码,请像这样更改 TryGetIndex:

public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) {
    // this will be called when you do myDict[index] (but not myDict[index] = something)
    if (indexes.Length != 1)
        throw new Exception("Only 1-dimensional indexer is supported");
    var index = indexes[0];
    // if our internal dictionary does not contain this key
    // return null
    if (!_dictionary.ContainsKey(index)) {
        result = null;
    }
    else {
        result = _dictionary[index];
    }
    return true;
}

然后你需要检查这样的 key 是否已经存在(我认为这更好一点):

dynamic termsTable = new DynamicDictionary();
var name = "name";
int commodityId = 123;
var year = DateTime.Now.Year + 5;
// need to check if such key exists
// like isset in php
if (termsTable[name] == null)
    termsTable[name] = new DynamicDictionary();
if (termsTable[name][commodityId] == null)
    termsTable[name][commodityId] = new DynamicDictionary();
for (int y = 2008; y <= year; y++) {
    if (termsTable[name][commodityId][y] == null)
        termsTable[name][commodityId][y] = new DynamicDictionary();
    for (int i = 1; i < 12; i++) {
        // that's fine
        termsTable[name][commodityId][y][i] = 0;
    }
}

当然,这样做会把类型安全抛到九霄云外,但如果您不介意,那为什么不呢。

关于c# - 复制PHP的动态多维数组创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47592532/

相关文章:

c# - System.Threading.Timer 回调永远不会被调用

php - 如何用php和mysql计算剩余时间?

c++ - 基于数组的有界缓冲区中的空元素

c++ - 'struct ListNode' 类型的空指针内的成员访问

c# - TcpClient 瓶颈

c# - 从 appsettings.json 获取 ConnectionString,而不是在 .NET Core 2.0 应用程序中硬编码

php - 如何在php中循环?

php - PHP 中的 if-else 与多个条件

java - Vector 与 ArrayList 同步的示例

c# - LINQ 查询从对象列表中返回不同的字段值