$result = array();
foreach ($array as $array2) {
foreach ($array2 as $values) {
$result[$values['year']][$values['sem']][] = $values;
}
}
Сначала создайте массив $result
для сохранения результата. Затем выполните цикл по двум вложенным массивам, чтобы добраться до самого внутреннего массива $values
со значениями year
и sem
.
Оба значения year
и sem
каждого массива $values
затем используются в качестве ключей, когда массив $values
добавляется в массив $result
. Это сортирует значения по годам, а затем по семестрам.
Результат:
Array
(
[3] => Array
(
[s2] => Array
(
[0] => Array
(
[sem] => s2
[year] => 3
[subjectcode] => web
[subjectname] => webtechnology
[internal] => 30
[external] => 65
[credits] => 3
)
[1] => Array
(
[sem] => s2
[year] => 3
[subjectcode] => js654
[subjectname] => java
[internal] => 25
[external] => 60
[credits] => 3
)
)
)
)
У меня была эта проблема, но вместо того, чтобы использовать отражение, я закончил тем просто, что проверил, был ли это IEnumerable. Вся реализация наборов это.
if (item is IEnumerable)
{
foreach (object o in (item as IEnumerable))
{
}
} else {
// reflect over item
}
Я попытался использовать подобную технику в качестве предложенного Darren, однако просто остерегаться этого не просто, наборы реализуют IEnumerable. string
, например, также IEnumerable и выполнит итерации по символам.
Вот небольшая функция, которую я использую, чтобы определить, является ли объект набором (который будет счетным также, так как ICollection является также IEnumerable).
public bool isCollection(object o)
{
return typeof(ICollection).IsAssignableFrom(o.GetType())
|| typeof(ICollection<>).IsAssignableFrom(o.GetType());
}
Просто получите значение свойства и затем бросьте его в IEnumerable. Вот некоторый (непротестированный) код для давания Вам общее представление:
ClassWithListProperty obj = new ClassWithListProperty();
obj.List.Add(1);
obj.List.Add(2);
obj.List.Add(3);
Type type = obj.GetType();
PropertyInfo listProperty = type.GetProperty("List", BindingFlags.Public);
IEnumerable listObject = (IEnumerable) listProperty.GetValue(obj, null);
foreach (int i in listObject)
Console.Write(i); // should print out 123
Я посмотрел бы на Тип. Метод FindInterfaces. Это может отфильтровать интерфейсы, реализованные данным типом. Как в PropertyInfo. PropertyType. FindInterfaces (filterMethod, filterObjects). Можно отфильтровать IEnumerable и видеть, возвращаются ли какие-либо результаты. MSDN имеет яркий пример в документации метода.
Довольно простой подход должен был бы ввести, снимает объект в качестве набора и непосредственно используют это.
Лучшее, которое Вы могли, вероятно, сделать, должно будет проверить, реализует ли объект определенные интерфейсы набора - вероятно, IEnumerable был бы всем, в чем Вы нуждаетесь. Затем это - просто вопрос вызова GetEnumerator () прочь объекта и использования IEnumerator. MoveNext () и IEnumerator. Текущий для прокладывания себе путь через набор.
Это не поможет Вам, если набор не реализует те интерфейсы, но если это так это не действительно большая часть набора, я предполагаю.
Когда Ваше отражение использования Вы не обязательно используете экземпляр того объекта. Необходимо было бы создать экземпляр того типа смочь выполнить итерации через свойства объекта. Таким образом, если Вы используете использование отражения ConstructorInfo. Вызовите () (?) метод, чтобы создать новый экземпляр или указать на экземпляр типа.
Если вы используете не экземпляр объекта, а тип, вы можете использовать следующее:
// type is IEnumerable
if (type.GetInterface("IEnumerable") != null)
{
}