最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Javascript: Filter an object by value and return new object (not an array) - Stack Overflow

programmeradmin5浏览0评论

I have two JS related objects with IDs. I need to filter the first object based on second object value color. The filter function works for me but I get an array, I need an object.

The objects are similar like this:

"matchs": { 
  "123": { 
    id: "123",            
    array_players: [ "1","2" ],    
  },
  "345": { 
    id: "345",            
    array_players: [ "1","4" ],    
  },
  "611": { 
    id: "611",            
    array_players: [ "2","5" ],    
  }  
};

"players": {
  "1": { "id": "1", "name": "Mike", color: "green"},
  "2": { "id": "2", "name": "Andy", color: "yellow" },
  "3": { "id": "3", "name": "Tony", color: "blue"},
  "4": { "id": "4", "name": "Joe", color: "green" }
  "5": { "id": "4", "name": "Lisa", color: "red" }
}

The ES6 filter function:

var filter = Object.values(matchs).filter(function(match){
  return (
    match.array_players.find (function(player_id){
      return (players[player_id].color === 'green')
    })
  );
});

But the result is an array not object like original matchs:

[ 
  0: { 
    id: "123",            
    array_players: [ "1","2" ],    
  },
  1: { 
    id: "345",            
    array_players: [ "1","4" ],    
  }      
];

I'll need something like this:

"matchs": { 
  "123": { 
    id: "123",            
    array_players: [ "1","2" ],    
  },
  "345": { 
    id: "345",            
    array_players: [ "1","4" ],    
  }, 
};

I have two JS related objects with IDs. I need to filter the first object based on second object value color. The filter function works for me but I get an array, I need an object.

The objects are similar like this:

"matchs": { 
  "123": { 
    id: "123",            
    array_players: [ "1","2" ],    
  },
  "345": { 
    id: "345",            
    array_players: [ "1","4" ],    
  },
  "611": { 
    id: "611",            
    array_players: [ "2","5" ],    
  }  
};

"players": {
  "1": { "id": "1", "name": "Mike", color: "green"},
  "2": { "id": "2", "name": "Andy", color: "yellow" },
  "3": { "id": "3", "name": "Tony", color: "blue"},
  "4": { "id": "4", "name": "Joe", color: "green" }
  "5": { "id": "4", "name": "Lisa", color: "red" }
}

The ES6 filter function:

var filter = Object.values(matchs).filter(function(match){
  return (
    match.array_players.find (function(player_id){
      return (players[player_id].color === 'green')
    })
  );
});

But the result is an array not object like original matchs:

[ 
  0: { 
    id: "123",            
    array_players: [ "1","2" ],    
  },
  1: { 
    id: "345",            
    array_players: [ "1","4" ],    
  }      
];

I'll need something like this:

"matchs": { 
  "123": { 
    id: "123",            
    array_players: [ "1","2" ],    
  },
  "345": { 
    id: "345",            
    array_players: [ "1","4" ],    
  }, 
};
Share Improve this question asked Jan 11, 2018 at 18:03 kurtkokurtko 2,1364 gold badges33 silver badges49 bronze badges 1
  • Try lodash or underscore with find - returns the 1st object that matches – Phil Boyd Commented Jan 11, 2018 at 18:05
Add a ment  | 

4 Answers 4

Reset to default 4

You could map the objects and use Object.assign for getting all objects into a single object.

var matchs = { 123: { id: "123", array_players: ["1", "2"] }, 345: { id: "345", array_players: ["1", "4"] }, 611: { id: "611", array_players: ["2", "5"] } },
    players = { 1: { id: "1", name: "Mike", color: "green" }, 2: { id: "2", name: "Andy", color: "yellow" }, 3: { id: "3", name: "Tony", color: "blue" }, 4: { id: "4", name: "Joe", color: "green" }, 5: { id: "4", name: "Lisa", color: "red" } },
    result = Object.assign(
        {},
        ...Object
            .keys(matchs)
            .filter(k => matchs[k].array_players.some(l => players[l].color === 'green'))
            .map(k => ({ [k]: matchs[k] }))
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You can add another step of Array#reduce to fold the array of matches down to an object.

I would also avoid using Object.values as it is only patible with modern browsers and would require a shim. You can use Object.keys to do the same but with more patibility.

const matches = { 
  "123": { 
    id: "123",            
    array_players: [ "1","2" ],    
  },
  "345": { 
    id: "345",            
    array_players: [ "1","4" ],    
  },
  "611": { 
    id: "611",            
    array_players: [ "2","5" ],    
  }  
};

const players = {
  "1": { "id": "1", "name": "Mike", color: "green"},
  "2": { "id": "2", "name": "Andy", color: "yellow" },
  "3": { "id": "3", "name": "Tony", color: "blue"},
  "4": { "id": "4", "name": "Joe", color: "green" },
  "5": { "id": "4", "name": "Lisa", color: "red" }
}

const filterByPlayerColor = (color, players) => 
  Object.keys(matches).filter(x =>
    matches[x].array_players.find(id => players[id].color === color)
  )
  .reduce((acc, x) => ({ ...acc, [x]: matches[x] }), {})

console.log(
  filterByPlayerColor('green', players)
)
<script src="https://codepen.io/synthet1c/pen/KyQQmL.js"></script>

  const result = {};

  for(const {id, array_players} of Object.values(matchs))
     result[id] = {id, array_players: array_players.filter(playerID => players[playerID].color === "green")};

You need to set up a new object and set its properties.

try to use a reducer and build the resultant object. try this one,

let _iterator = (val) => {
    return players[val].color === 'green'
  }

let _reducer = (acc, currVal, currIndex, arr) => {
  let res = matchs[arr[currIndex]].array_players.some(_iterator);
  res && (acc[arr[currIndex]] = matchs[arr[currIndex]]);
  return acc;
}

let result = {matchs: Object.keys(matchs).reduce(_reducer, {})};
console.log(result)
发布评论

评论列表(0)

  1. 暂无评论