简体   繁体   English

从一个数组中删除元素并将它们添加到一个新数组中

[英]Remove elements from one array and add them to a new array

I have an array of objects containing world countries with some additional information eg我有一系列包含世界国家的对象以及一些附加信息,例如

countries = [
  {
    flag: 'assets/flags/angola.svg',
    code: 'AGO',
    name: 'Angola',
    regions: [{
      name: 'Luanda'
    }]
  },
  {
    flag: 'assets/flags/albania.svg',
    code: 'ALB',
    name: 'Albania',
    regions: [{
      name: 'Korça'
    }, {
      name: 'Tirana'
    }, {
      name: 'Gjirokastër'
    }]
  }...

I want to extract three of my favorite countries into a new array while removing them from the original array so I end up with two arrays one for my favorite countries and one for the rest of the countries.我想将三个我最喜欢的国家提取到一个新数组中,同时将它们从原始数组中删除,所以我最终得到两个 arrays 一个用于我最喜欢的国家,一个用于 rest 国家。

I managed to achieve this the following way:我设法通过以下方式实现了这一目标:

public createCountriesList(allCountries: Country[]) {

let topCountries: Country[] = [];
let restOfCountries: Country[];

allCountries.forEach((element) => {
  switch (element.code) {
    case 'HRV':
      topCountries.push(element);
      break;
    case 'AT':
      topCountries.push(element);
      break;
    case 'GER':
      topCountries.push(element);
      break;
  }
});

restOfCountries = allCountries.filter((c) => {
  return !topCountries.includes(c);
});}

It works, but I was wondering if there is a more elegant way to do this?它有效,但我想知道是否有更优雅的方法来做到这一点?

Everything seems fine according to me... Obviously you need two arrays one for the extracted ones and second for rest of countries.根据我的说法,一切似乎都很好......显然你需要两个 arrays 一个用于提取的,第二个用于 rest 的国家。

One thing we can work on is the switch case.我们可以做的一件事是开关盒。

Instead of switch case you can use .includes function. Store the name of countries you want to extract in an array.您可以使用.includes function 代替 switch case。将要提取的国家/地区的名称存储在数组中。

const arr = ['HRV','AT','GR']

now you can do,现在你可以做,

if(arr.includes(element.code)){
//push into new array
} else{
//push into another 
}

One more thing you can do is save restOfTheCountries using .filter function. Just return true for the countries which fails your above if case.您可以做的另一件事是使用.filter function 保存restOfTheCountries 。如果情况不符合上述情况,只需返回 true 即可。

I would probably create a separate generic function for splitting array based on the criteria (using ts since you are)我可能会创建一个单独的通用 function 用于根据条件拆分数组(使用 ts 因为你是)

const splitArray = <T>(array: Array<T>, matchFunction: (el: T) => boolean) => {
  const matching: T[] = [], nonMatching: T[] = []
  array.forEach(el => matchFunction(el) ? matching.push(el) : nonMatching.push(el))
  return [matching, nonMatching]
}

then you can call it with the array and a function然后你可以用数组和 function 调用它

const [topCountries, restOfCountries] = splitArray(countries, c => ["HRV", "AT", "GER"].includes(c.code))

that would be a bit more readable.那会更具可读性。 a more elegant solution is to extend Array with that functionality ( Array.prototype.split ) then using countries.split(c => ["HRV", "AT", "GER"].includes(c.code))一个更优雅的解决方案是使用该功能( Array.prototype.split )扩展 Array 然后使用countries.split(c => ["HRV", "AT", "GER"].includes(c.code))

You can just use regular filter to split the array:您可以只使用常规过滤器来拆分数组:

const isTop = ({code}) => ['HRV','AT','GR'].includes(code);
const topCountries = allCountries.filter(isTop);
const restOfCountries = allCountries.filter((contry) => !isTop(contry));

Another way, you can add a property that shows whether this country is top or not, and filter by this key另一种方式,你可以添加一个属性来显示这个国家是否是顶级的,并通过这个键过滤

const withTop = countries.map((e) => ({...e, top: ['AGO','AT','GR'].includes(e.code)}));

// {
//   code: "AGO"
//   flag: "assets/flags/angola.svg"
//   name: "Angola"
//   regions: [{…}]
//   top: true
// }

All suggestions so far seem valid, I ended up using @Alexandr Belan answer as it was the most straightforward to implement in my case, I don't know why I used switch case instead of filter like for the topCountries ♂️.到目前为止,所有建议似乎都是有效的,我最终使用了@Alexandr Belan 的答案,因为它在我的案例中是最直接实现的,我不知道为什么我使用 switch case 而不是像 topCountries ♂️ 那样的过滤器。 Final code (added alphabetical sorting of the countries as well)最终代码(也添加了国家/地区的字母排序)

  const suggestedCountriesList = ['Brazil', 'France', 'Germany'];
    const suggested = ({ name }) => suggestedCountriesList.includes(name);
    const suggestedCountries = allCountries.filter(suggested);
    const otherCountries = allCountries.filter((country) => !suggested(country));

// sort alphabetically
    otherCountries.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
    suggestedCountries.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()));


    return [suggestedCountries, otherCountries];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM