1

There are 2 json arrays below.

arrayA = [
    {attr1: "text", attr2: true, field: "format4"},
    {attr1: "text", attr2: true, field: "format2"},
    {attr1: "text", attr2: true, field: "format1"},
    {attr1: "text", attr2: true, field: "format3"}];

arrayB = [
    { name: 'format1', type: 'text' },
    { name: 'format2', type: 'text' },
    { name: 'format3', type: 'text' },
    { name: 'format4', type: 'text' }
];

I want to sort array B name by array A's field my goal is like this

arrayB = [
    { name: 'format4', type: 'text' },
    { name: 'format2', type: 'text' },
    { name: 'format1', type: 'text' },
    { name: 'format3', type: 'text' }
];

I thought like this but this is not my goal.

arrayB = arrayA.map((a) => {
    return arrayB.filter((b) => {
        return a.field === b.name 
    });
});

please give me a advise for accomplish my goal.

3 Answers3

3

If you are comfortable using ES6 features, you can use Array.findIndex to get the index and return difference

Array.findIndex

var arrayA = [{attr1: "text", attr2: true, field: "format4"}, {attr1: "text", attr2: true, field: "format2"}, {attr1: "text", attr2: true, field: "format1"}, {attr1: "text", attr2: true, field: "format3"}];

var arrayB = [ { name: 'format1', type: 'text' }, { name: 'format2', type: 'text' }, { name: 'format3', type: 'text' }, { name: 'format4', type: 'text' }];

function getIndexInArrayA(name) {
  return arrayA.findIndex(function(obj){ return obj.field === name})
}
arrayB.sort(function(a, b) {
  return getIndexInArrayA(a.name) - getIndexInArrayA(b.name);
});

console.log(arrayB)

HashMap

Loop over array and create a map that holds name and index. This way you do not need to loop over array to get index.

Note: This is more preferred as it involves less iterations. retrieving data from object is faster than getting index form array.

var arrayA = [{attr1: "text", attr2: true, field: "format4"}, {attr1: "text", attr2: true, field: "format2"}, {attr1: "text", attr2: true, field: "format1"}, {attr1: "text", attr2: true, field: "format3"}];

var arrayB = [ { name: 'format1', type: 'text' }, { name: 'format2', type: 'text' }, { name: 'format3', type: 'text' }, { name: 'format4', type: 'text' }];

var indexNameMap = arrayA.reduce(function(acc, obj, i) {
  acc[obj.field] = i;
  return acc;
}, {})
arrayB.sort(function(a, b) {
  return indexNameMap[a.name] - indexNameMap[b.name];
});

console.log(arrayB)
Community
  • 1
  • 1
Rajesh
  • 24,354
  • 5
  • 48
  • 79
  • Polyfill: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex#Polyfill – Nisarg Shah Jan 31 '18 at 05:08
  • @NisargShah Thanks for the link, but I've put caveats for using ES6. Apart from that, I have added another solution that would work for ES5 as well. You can check it. – Rajesh Jan 31 '18 at 05:12
  • @通りすがりのおっさん Glad I was able to help! :-) – Rajesh Jan 31 '18 at 06:33
  • @OriDrori Valid point but thought of answering it. Also ion your mentioned link, I dont think hashMap case is covered, which makes it valid(*not duplicating content*). If you find this approach also covered, please tell me and I'll remove my answer. :-) Also, linked dupe has redundant values. Thats a different question altogether – Rajesh Jan 31 '18 at 07:31
2

You can try following

var arrayA = [{attr1: "text", attr2: true, field: "format4"}, {attr1: "text", attr2: true, field: "format2"}, {attr1: "text", attr2: true, field: "format1"}, {attr1: "text", attr2: true, field: "format3"}];

var arrayB = [ { name: 'format1', type: 'text' }, { name: 'format2', type: 'text' }, { name: 'format3', type: 'text' }, { name: 'format4', type: 'text' }];

// Create a temporary array of fields of array A 
var tempArr = arrayA.map(function(item) {
  return item.field;
});

// Create custom sort function to sort based on temp Arr
arrayB.sort(function(a, b) {
  return tempArr.indexOf(a.name) - tempArr.indexOf(b.name);
})

console.log(arrayB);
Nikhil Aggarwal
  • 28,197
  • 4
  • 43
  • 59
0

another solution:

const res = _.map(arrayA, a => _.find(arrayB, { name: a.field }));
stasovlas
  • 7,136
  • 2
  • 28
  • 29