合并 3 个集合以每行返回一个对象

Posted

技术标签:

【中文标题】合并 3 个集合以每行返回一个对象【英文标题】:Merging 3 collections to return one object per row 【发布时间】:2019-12-31 03:31:13 【问题描述】:

我正在使用 axios 将城镇、州和国家返回到 Vue 2 自动完成字段。查询的字段都在同一个表中;地点。如果我只返回城镇,该领域的效果很好,但世界上有很多城镇同名,所以我想返回城镇所在的州/地区和国家/地区。我遇到的问题是让我的控制器为城镇、州和国家输出一个对象,而不是将它们合并为单独的对象。

我尝试过使用 Eloquent 提供的 merge、put 和 combine 方法。 Merge and put 将给我一个包含 6 个对象的数组,其中包含我的测试数据,即伯明翰,因为在英格兰西米德兰兹郡有一个,在美国阿拉巴马州有一个。对象 0 和 1 具有城镇 id、城镇名称和父 id,2 和 3 具有州 id 等,4 和 5 具有国家 id 等。在 Google 和此处搜索大多数说合并的答案,但实际上不会每个单独的集合到一个对象中。

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use \App\Location;

class AjaxLocationsController extends Controller 
public function index(Request $request) 
$searchquery = $request->searchquery;
$states = collect();
$countries = collect();
$all_details = collect();

    $locations = Location::select('id', 'location', 'parent_id')
    ->where([['id', '>', 4351], ['location', 'like', '%' . $searchquery . '%']])
    ->orderBy('location')
    ->get();

    foreach($locations as $location)
    

        $state = Location::select('id as state_id', 'location as state', 'parent_id as state_parent_id')
        ->where('id', '=', $location->parent_id)
        ->get();

        $states->push($state);
    

    $states = $states->flatten();

    foreach($states as $state)
    
        $country = Location::select('id as country_id', 'location as country')
        ->where('id', '=', $state->state_parent_id)
        ->get();

        $countries->push($country);
    

    $countries = $countries->flatten();

    $all_details = $all_details->merge($locations);
    $all_details = $all_details->merge($states);
    $all_details = $all_details->merge($countries);
    $all_details = $all_details->flatten();

    return $all_details;

我原以为这很容易做到,虽然我对 Laravel (5.8) 很陌生,但我在使用 php 数组方面有很多经验。我想我一定是错过了什么,因为我整天都在做这件事!

任何帮助将不胜感激。

【问题讨论】:

对 PHP 无能为力,但只返回多个对象/多个数组,然后以您想要的任何方式将它们与插槽一起显示并不难。您需要将它们配对,但如果您说一个包含许多较小对象的大对象,那么这将起作用。或索引匹配的并行数组。 感谢您的评论,迈克尔。这几乎是我想要实现的目标,但是以 Eloquent(即 Laravel)的方式。 【参考方案1】:

我已经想出了我想说的更像是一种非 Eloquent 的方法,但我会在这里发布我的代码,希望它能帮助其他遇到相同类型问题的人。 ajax 响应非常快(大约 100 毫秒),所以我对结果非常满意。如果其他人有更好(更雄辩)的解决方案,请在此处发布答案。干杯!

Ajax 控制器

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use \App\Location;

class AjaxLocationsController extends Controller

    public function index(Request $request)
    
    $searchquery = $request->searchquery;
    $states = collect();
    $countries = collect();
    $all_details = collect();
    $counter = 0;

    $locations = Location::select('id', 'location', 'parent_id')
    ->where([['id', '>', 4351], ['location', 'like', '%' . $searchquery . '%']])
    ->orderBy('location')
    ->get();

    foreach ($locations as $location)
    
        $state = Location::select('id as state_id', 'location as state', 'parent_id as state_parent_id')
        ->where('id', '=', $location->parent_id)
        ->get();

        $states->push($state);
    

    $states = $states->flatten();

    foreach ($states as $state)
    
        $country = Location::select('id as country_id', 'location as country')
        ->where('id', '=', $state->state_parent_id)
        ->get();

        $countries->push($country);
    

    $countries = $countries->flatten();

    foreach ($locations as $location)
    
        $full_location = collect([
            'id' => $location->id,
            'location' => $location->location,
            'parent_id' => $location->parent_id,
            'state_id' => $states[$counter]['state_id'],
            'state' => $states[$counter]['state'],
            'state_parent_id' => $states[$counter]['state_parent_id'],
            'country_id' => $countries[$counter]['country_id'],
            'country' => $countries[$counter]['country'],
        ]);

        $all_details = $all_details->push($full_location);
        $counter++;
    

    return $all_details;



Vue Component

<template>
<div>
    <label for="searchquery">Town</label>
    <input type="text" v-model="searchquery" v-on:keyup="getLocations" class="form- 
control">
    <div class="panel-footer" v-if="data_results.length">
        <ul class="list-group">
            <a href="#" @click="setLocation(result)" class="list-group-item list- 
group-item-action" v-for="result in data_results" :key="result.id"> result.location 
,  result.state ,  result.country </a>
        </ul>
    </div>
</div>
</template>
<script>
export default 
    data() 
    return 
        searchquery: '',
        data_results: []
    
,
methods: 
    getLocations() 
        this.data_results = [];
        if (this.searchquery.length > 1) 
            axios.get('/get-locations',  params:  searchquery: this.searchquery  )
                .then(response => 
                    console.log(response);
                    this.data_results = response.data;
                );
        
    ,
    setLocation(result) 
        this.searchquery = result.location + ', ' + result.state + ', ' + result.country;
        this.data_results = [];
    
,

</script>

【讨论】:

以上是关于合并 3 个集合以每行返回一个对象的主要内容,如果未能解决你的问题,请参考以下文章

2021-09-28:合并区间。以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠

java怎么合并list对象集合

将 3 个数据集合并在一起

836. 合并集合(并查集)

根据条件合并 2 个集合以填充嵌套集合

List集合中的对象根据某个相同的属性,合并另外属性