将嵌套对象合并到一个级别

时间:2019-04-11 07:23:12

标签: recursion dart reduce

我在飞镖课上上课

//FOR DESIGN

private Toolbar toolbar;

private DrawerLayout drawerLayout;
private NavigationView navigationView;

//FOR FRAGMENTS
private Fragment fragmentIntro;
private Fragment fragmentPhoto;
private Fragment fragmentProfile;
private Fragment fragmentDossier;
private Fragment fragmentDate;
private Fragment fragmentZone;
private Fragment fragmentTypeIntervention;


//FOR DATAS
private static final int FRAGMENT_INTRO = 0;
private static final int FRAGMENT_PHOTO = 1;
private static final int FRAGMENT_PROFILE = 2;
private static final int FRAGMENT_DOSSIER = 3;
private static final int FRAGMENT_DATE = 4;
private static final int FRAGMENT_ZONE = 5;
private static final int FRAGMENT_TYPE_INTERVENTION = 6;


// FOR STRINGS

private static TextView mFragmentPageNewsTitle;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Configure all views
    this.configureToolBar();
    this.configureDrawerLayout();
    this.configureNavigationView();

    // Show First Fragment
    this.showFirstFragment();
}

@Override
public void onBackPressed() {
    // Handle back click to close menu
    if (this.drawerLayout.isDrawerOpen(GravityCompat.START)) {
        this.drawerLayout.closeDrawer(GravityCompat.START);
    } else {
        super.onBackPressed();
    }
}


@Override
public boolean onNavigationItemSelected(MenuItem item) {

    int id = item.getItemId();

    // Show fragment after user clicked on a menu item
    switch (id){

        case R.id.activity_main_drawer_intro :
            this.showFragment(FRAGMENT_INTRO);
            break;

        case R.id.activity_main_drawer_photo :
            this.showFragment(FRAGMENT_PHOTO);
            break;

        case R.id.activity_main_drawer_profile:
            this.showFragment(FRAGMENT_PROFILE);
            break;
        case R.id.activity_main_drawer_dossier:
            this.showFragment(FRAGMENT_DOSSIER);
            break;

        case R.id.activity_main_drawer_date:
            this.showFragment(FRAGMENT_DATE);
            break;

        case R.id.activity_main_drawer_zone:
            this.showFragment(FRAGMENT_ZONE);
            break;

        case R.id.activity_main_drawer_typeintervention:
            this.showFragment(FRAGMENT_TYPE_INTERVENTION);
            break;

        default:
            break;
    }

    this.drawerLayout.closeDrawer(GravityCompat.START);
    return true;
}





// ---------------------
// CONFIGURATION
// ---------------------

// Configure Toolbar
private void configureToolBar(){
    this.toolbar = (Toolbar) findViewById(R.id.activity_main_toolbar);
    setSupportActionBar(toolbar);
}

// Configure Drawer Layout
private void configureDrawerLayout(){
    this.drawerLayout = (DrawerLayout) findViewById(R.id.activity_main_drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawerLayout.addDrawerListener(toggle);
    toggle.syncState();
}

// Configure NavigationView
private void configureNavigationView(){
    this.navigationView = (NavigationView) findViewById(R.id.activity_main_nav_view);
    navigationView.setNavigationItemSelectedListener(this);
}

// ---------------------
// FRAGMENTS
// ---------------------

// Show first fragment when activity is created
private void showFirstFragment(){
    Fragment visibleFragment = getSupportFragmentManager().findFragmentById(R.id.activity_main_frame_layout);
    if (visibleFragment == null){
        // Show Photo Fragment
        this.showFragment(FRAGMENT_INTRO);
        // Mark as selected the menu item corresponding to PhotoFragment
        this.navigationView.getMenu().getItem(0).setChecked(true);
    }
}

// Show fragment according an Identifier
private void showFragment(int fragmentIdentifier){
    switch (fragmentIdentifier){

        case FRAGMENT_INTRO :
            this.showIntroFragment();
            break;

        case FRAGMENT_PHOTO :
            this.showPhotoFragment();
            break;
        case FRAGMENT_PROFILE:
            this.showProfileFragment();
            break;
        case FRAGMENT_DOSSIER:
            this.showClientsFragment();
            break;

        case FRAGMENT_DATE:
            this.showDateFragment();
            break;

        case FRAGMENT_ZONE:
            this.showZoneFragment();
            break;

        case FRAGMENT_TYPE_INTERVENTION:
            this.showTypeInterventionFragment();
            break;

        default:
            break;
    }
}

// ---

// Create each fragment page and show it
private void showIntroFragment() {
    if (this.fragmentIntro == null) this.fragmentIntro = IntroFragment.newInstance();
    this.startTransactionFragment(this.fragmentIntro);
}

private void showPhotoFragment(){
    if (this.fragmentPhoto == null) this.fragmentPhoto = PhotoFragment.newInstance();
    this.startTransactionFragment(this.fragmentPhoto);
}

private void showClientsFragment(){
    if (this.fragmentDossier == null) this.fragmentDossier = DossierFragment.newInstance();
    this.startTransactionFragment(this.fragmentDossier);
}

private void showProfileFragment(){
    if (this.fragmentProfile == null) this.fragmentProfile = ProfileFragment.newInstance();
    this.startTransactionFragment(this.fragmentProfile);
}

private void showDateFragment(){
    if (this.fragmentDate == null) this.fragmentDate = DateFragment.newInstance();
    this.startTransactionFragment(this.fragmentDate);
}

private void showZoneFragment(){
    if (this.fragmentZone == null) this.fragmentZone = ZoneFragment.newInstance();
    this.startTransactionFragment(this.fragmentZone);
}

private void showTypeInterventionFragment(){
    if (this.fragmentTypeIntervention == null) this.fragmentTypeIntervention = TypeInterventionFragment.newInstance();
    this.startTransactionFragment(this.fragmentTypeIntervention);
}



// ---

// Generic method that will replace and show a fragment inside the MainActivity Frame Layout
private void startTransactionFragment(Fragment fragment){
    if (!fragment.isVisible()){
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.activity_main_frame_layout, fragment).commit();
    }
}

我从api接收的数据在单个数组中返回所有注释(无论处于什么级别)。 parentCommentId用于指向答复的父级。要将这些数据转换为嵌套结构,

class PostComment {
  int id;
  int title;
  int parentCommentId;
  List<PostComment> replies;
}

使用此代码,我在下面的结构中获得了注释数组。

void toNestedComments({List<PostComment> comments}) {
  comments.forEach((postComment) {
    if (postComment.parentCommentId != null) {
      PostComment parentComment = comments.firstWhere((comment) => comment.id == postComment.parentCommentId, orElse: () => null);
      parentComment.replies.add(postComment);
    }
  });

  comments.removeWhere((c) => c.parentCommentId != null);
}

但是,UI要求数据显示如下。

Post 1
    - Post 11
    - Post 12
        - Post 121
        - Post 122
    - Post 13
Post 2
    - Post 21
        - Post 211   

您会建议对上述功能进行哪些修改以实现上述结构?

当前代码和数据结构位于https://dartpad.dartlang.org/6231828b3ea9dc1e956e87353394dae7

2 个答案:

答案 0 :(得分:0)

我不确定您的数据结构,但我想您可以执行以下操作:

像这样扩展PostComment类:

class PostComment {
  int id;
  int title;
  int parentCommentId;
  List<PostComment> replies = [];

  Iterable<PostComment> thisAndNestedReplies() sync* {
    yield this;
    for (var reply in replies) {
      yield* reply.thisAndNestedReplies();
    }
  }
}

然后您可以执行以下操作(我仍在使用您的方法来获取嵌套的数据结构):

toNestedComments(comments: comments);
var newList = comments
    .where((postComment) => postComment.parentCommentId == null)
    .expand((postComment) => postComment.thisAndNestedReplies()).toList();

答案 1 :(得分:-1)

PostComment实体中没有任何业务逻辑的解决方案。
数据查询中的所有逻辑都在函数main中。

import 'package:queries/collections.dart';

import 'dart:core';
import 'dart:convert';

void main() {
  var comments = Collection(getComments());
  var query = comments
      .groupJoin(
          comments,
          (o) => o.id,
          (i) => i.parentCommentId,
          (o, i) =>
              o..comments.addAll((i as IEnumerable<PostComment>).toList()))
      .where((p) => p.parentCommentId == null);
  printComments(query.toList(), 0);
}

void printComments(List<PostComment> comments, int indent) {
  for (var comment in comments) {
    var sb = StringBuffer();
    sb.write(''.padLeft(indent, '  '));
    sb.write(comment.id);
    print(sb);
    printComments(comment.comments, indent + 1);
  }
}

// Json with the all the comments. Replies to comment have parentCommentId set.
String json = '''
{
  "comments": [
    {
      "id": 35,
      "description": "Post 1",
      "parentCommentId": null
    },
    {
      "id": 36,
      "description": "Post 11",
      "parentCommentId": 35
    },
    {
      "id": 37,
      "description": "Post 111",
      "parentCommentId": 36
    },
    {
      "id": 38,
      "description": "Post 2",
      "parentCommentId": null

    },
    {
      "id": 39,
      "description": "Post 3",
      "parentCommentId": null
    },
    {
      "id": 61,
      "description": "Post 2",
      "parentCommentId": 35
    },
    {
      "id": 62,
      "description": "Post 21",
      "parentCommentId": 61
    },
    {
      "id": 64,
      "description": "Post 211",
      "parentCommentId": 62
    }
  ]
}
''';

List<PostComment> getComments() {
  var comments = <PostComment>[];
  final responseMap = jsonDecode(json);
  responseMap['comments'].forEach((i) {
    comments.add(PostComment.fromJson(i));
  });

  return comments;
}

class PostComment {
  PostComment({this.id, this.description, this.parentCommentId, this.postId});

  int id;
  String description;
  int parentCommentId;
  int postId;
  List<PostComment> comments;

  factory PostComment.fromJson(Map<String, dynamic> map) {
    final commentInfo = map;

    final _comment = PostComment(
      id: commentInfo['id'],
      description: commentInfo['description'],
      postId: commentInfo['postId'],
      parentCommentId: int.tryParse(commentInfo['parentCommentId'].toString()),
    );

    _comment.comments = List<PostComment>();
    return _comment;
  }

  String toString() {
    return this.description;
  }
}

结果:

35 36 37 61 62 64 38 39

PS

使用此代码i as IEnumerable<PostComment>是因为当前Dart编译器无法推断数据类型。看起来像编译器中的错误。