我想在处理当前项目并遍历IEnumerable<object>
时访问下一个和上一个项目(如果在范围内),据我所知,该List<object>
没有索引器。
尽管我现在唯一知道这是唯一的选择,但我并不需要一个public static void PrintTokens(IEnumerable<object> tokens)
{
foreach (var token in tokens)
{
// var next = ?
// var prev = ?
}
}
集合或一个数组来完成此操作。
如果可能的话,我也希望避免使用Linq表达式。
这就是我当前方法的定义方式:
import UIKit
struct User: Codable {
let firstName: String
let lastName: String
let email: String
let userid: String
enum CodingKeys: String, CodingKey {
case firstName = "first_name"
case lastName = "last_name"
case email = "email"
case userid = "user_id"
}
}
class tableViewCellLabels: UITableViewCell {
@IBOutlet var lbl_firstName: UILabel!
@IBOutlet var lbl_lastName: UILabel!
@IBOutlet var lbl_email: UILabel!
@IBOutlet var lbl_userid: UILabel!
}
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableview1: UITableView!
@IBOutlet var tableview2: UITableView!
private var dataSource = [User]() {
didSet {
self.tableview1.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.tableview1.dataSource = self
self.tableview1.delegate = self
let url = URL(string: "https://test.netperformers.de/users")
URLSession.shared.dataTask(with: url!, completionHandler: { [weak self] (data, response, error) in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "An error occurred")
return
}
DispatchQueue.main.async {
self?.dataSource = try! JSONDecoder().decode([User].self, from: data)
}
}).resume()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
tableview1.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView == tableView{
print(dataSource[indexPath.row]) // your clicked user data
}else{
// Second Tableview Click Event here
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "groupCell", for: indexPath) as! tableViewCellLabels
let user = self.dataSource[indexPath.row]
cell.lbl_firstName.text = user.firstName
cell.lbl_lastName.text = user.lastName
cell.lbl_userid.text = user.userid
return cell
}
func tableView1(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView == tableView{
print(dataSource[indexPath.row]) // your clicked user data
}else{
// Second Tableview Click Event here
}
}
}
答案 0 :(得分:3)
您可以像往常一样进行循环,但是您当前使用的项目变为next
,上一个项目为current
,而之前的项目为prev
。
object prev = null;
object current = null;
bool first = true;
foreach (var next in tokens)
{
if (!first)
{
Console.WriteLine("Processing {0}. Prev = {1}. Next = {2}", current, prev, next);
}
prev = current;
current = next;
first = false;
}
// Process the final item (if there is one)
if (!first)
{
Console.WriteLine("Processing {0}. Prev = {1}. Next = {2}", current, prev, null);
}
如果您使用的是C#7.0+,则可以编写
(prev, current, first) = (current, next, false);
而不是循环结束时的三个独立语句。
答案 1 :(得分:1)
我写了一个扩展方法,该方法返回一个包含三个对象的元组:上一个,当前和下一个:
public static class Extensions
{
public static IEnumerable<Tuple<T, T, T>> GetItems<T>(this IEnumerable<T> source)
where T : class
{
if (source != null)
{
// skip the first iteration to be able to include next item
bool skip = true;
T previous = default(T), current = default(T), next = default(T);
foreach (T item in source)
{
next = item;
if (!skip)
{
yield return new Tuple<T, T, T>(previous, current, next);
}
previous = current;
current = item;
skip = false;
}
if (!skip)
{
next = default(T);
yield return new Tuple<T, T, T>(previous, current, next);
}
}
}
}
希望有帮助。也许使用自定义类而不是元组进行扩展。
答案 2 :(得分:0)
U可以尝试这种扩展方法。它是“大小”上一个项目,“大小”下一个项目和当前项目:
public static System.Collections.Generic.IEnumerable<TResult> Select<TSource, TResult>(this System.Collections.Generic.IEnumerable<TSource> source, int size, System.Func<Queue<TSource>, TSource, Queue<TSource>, TResult> selector)
{
if (source == null)
{
throw new System.ArgumentNullException("source");
}
if (selector == null)
{
throw new System.ArgumentNullException("selector");
}
Queue<TSource> prevQueue = new Queue<TSource>(size);
Queue<TSource> nextQueue = new Queue<TSource>(size);
int i = 0;
foreach (TSource item in source)
{
nextQueue.Enqueue(item);
if (i++ >= size)
{
TSource it = nextQueue.Dequeue();
yield return selector(prevQueue, it, nextQueue);
prevQueue.Enqueue(it);
if (prevQueue.Count > size)
{
prevQueue.Dequeue();
}
}
}
while (nextQueue.Any())
{
TSource it = nextQueue.Dequeue();
yield return selector(prevQueue, it, nextQueue);
prevQueue.Enqueue(it);
if (prevQueue.Count > size)
{
prevQueue.Dequeue();
}
}
}
答案 3 :(得分:-1)
我认为原始的IEnumerable
不能提供,但是LinkedList可以提供。
答案 4 :(得分:-1)
摘自文档:
IEnumerable公开了一个枚举器,该枚举器支持简单的迭代。
因此,要实现所需的目标,可以采用以下四种方法之一:
ToList()
-这样,您可以按索引访问项目ElementAt()
方法,但是它会缺乏性能,因为每次调用此方法时都会枚举令牌IEnumerable<object> tokens
更改为IList<object> tokens