将lodash _.uniqBy()转换为本机javascript

时间:2016-11-25 09:16:32

标签: javascript arrays lodash distinct-values

在此片段中,我被卡在_.uniqBy(array,iteratee),这个

  • iteratee可以是函数或字符串同时
  • 在条件中检查uniqness的条件,因为itratee函数可以是任何

var sourceArray = [ { id: 1, name: 'bob' },
  { id: 1, name: 'bill' },
  { id: 1, name: 'bill' } ,
  {id: 2,name: 'silly'},
  {id: 2,name: 'billy'}]

function uniqBy (inputArray, callback) {
  return inputArray.filter(callback)
}
var inputFunc = function (item) {
  return item.name
}

// var destArray = _.uniqBy(sourceArray,'name')

var destArray = uniqBy(sourceArray, inputFunc)
console.log('destArray', destArray)

对此的任何线索都将非常感激。

4 个答案:

答案 0 :(得分:11)

ES6 import java.io.InputStream; import java.util.HashMap; import java.util.Map; import org.jacoco.core.analysis.Analyzer; import org.jacoco.core.analysis.CoverageBuilder; import org.jacoco.core.analysis.IClassCoverage; import org.jacoco.core.analysis.ICounter; import org.jacoco.core.data.ExecutionDataStore; import org.jacoco.core.instr.Instrumenter; import org.jacoco.core.runtime.IRuntime; import org.jacoco.core.runtime.LoggerRuntime; import org.junit.runner.JUnitCore; import org.junit.runner.Result; import org.jacoco.core.runtime.RuntimeData; import org.jacoco.core.data.SessionInfoStore; public class CoreTutorialTest { /** * A class loader that loads classes from in-memory data. */ public static class MemoryClassLoader extends ClassLoader { private final Map<String, byte[]> definitions = new HashMap<String, byte[]>(); /** * Add a in-memory representation of a class. * * @param name name of the class * @param bytes class definition */ public void addDefinition(final String name, final byte[] bytes) { definitions.put(name, bytes); } @Override protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException { final byte[] bytes = definitions.get(name); if (bytes != null) return defineClass(name, bytes, 0, bytes.length); return super.loadClass(name, resolve); } } private InputStream getTargetClass(final String name) { final String resource = '/' + name.replace('.', '/') + ".class"; return getClass().getResourceAsStream(resource); } private void printCounter(final String unit, final ICounter counter) { final Integer missed = Integer.valueOf(counter.getMissedCount()); final Integer total = Integer.valueOf(counter.getTotalCount()); System.out.printf("%s of %s %s missed%n", missed, total, unit); } private String getColor(final int status) { switch (status) { case ICounter.NOT_COVERED: return "red"; case ICounter.PARTLY_COVERED: return "yellow"; case ICounter.FULLY_COVERED: return "green"; } return ""; } private void runTutorial() throws Exception { final String targetName = Calculadora.class.getName(); // For instrumentation and runtime we need a IRuntime instance to collect execution data: final IRuntime runtime = new LoggerRuntime(); // The Instrumenter creates a modified version of our test target class that contains additional probes for execution data recording: final Instrumenter instr = new Instrumenter(runtime); final byte[] instrumented = instr.instrument(getTargetClass(targetName), ""); // Now we're ready to run our instrumented class and need to startup the runtime first: final RuntimeData data = new RuntimeData(); runtime.startup(data); // In this tutorial we use a special class loader to directly load the instrumented class definition from a byte[] instances. final MemoryClassLoader memoryClassLoader = new MemoryClassLoader(); memoryClassLoader.addDefinition(targetName, instrumented); final Class<?> targetClass = memoryClassLoader.loadClass(targetName); // Here we execute our test target class through its Runnable interface: /*final Runnable targetInstance = (Runnable) targetClass.newInstance(); targetInstance.run();*/ String junitName = CalculadoraTest.class.getName(); memoryClassLoader.addDefinition(junitName, instr.instrument(getTargetClass(junitName), "")); final Class<?> junitClass = memoryClassLoader.loadClass(junitName); JUnitCore junit = new JUnitCore(); Result result = junit.run(junitClass); System.out.println("Failure count: " + result.getFailureCount()); // At the end of test execution we collect execution data and shutdown the runtime: final ExecutionDataStore executionData = new ExecutionDataStore(); data.collect(executionData, new SessionInfoStore(), false); runtime.shutdown(); // Together with the original class definition we can calculate coverage information: final CoverageBuilder coverageBuilder = new CoverageBuilder(); final Analyzer analyzer = new Analyzer(executionData, coverageBuilder); analyzer.analyzeClass(getTargetClass(targetName), targetName); // Let's dump some metrics and line coverage information: for (final IClassCoverage cc : coverageBuilder.getClasses()) { System.out.printf("Coverage of class %s%n", cc.getName()); printCounter("instructions", cc.getInstructionCounter()); printCounter("branches", cc.getBranchCounter()); printCounter("lines", cc.getLineCounter()); printCounter("methods", cc.getMethodCounter()); printCounter("complexity", cc.getComplexityCounter()); for (int i = cc.getFirstLine(); i <= cc.getLastLine(); i++) { System.out.printf("Line %s: %s%n", Integer.valueOf(i), getColor(cc.getLine(i).getStatus())); } } } public static void main(final String[] args) throws Exception { new CoreTutorial().runTutorial(); } } 使用Map,复杂度为O(n):

&#13;
&#13;
uniqBy
&#13;
&#13;
&#13;

答案 1 :(得分:1)

我正在通过CreateReactApp通过Webpack运行代码,它必须使用polyfill进行传播,该传播使用slice。这是我所做的,是@oridori答案的变体:

const uniqBy = (arr: any[], predicate: (item: any) => string) => {
  const cb = typeof predicate === 'function' ? predicate : (o) => o[predicate];
  const result = [];
  const map = new Map();

  arr.forEach((item) => {
    const key = (item === null || item === undefined) ? item : cb(item);

    if (!map.has(key)) {
      map.set(key, item);
      result.push(item);
    }
  });

  return result;
};

答案 2 :(得分:1)

重构@ ori-drori的解决方案并删除

  1. undefined
  2. null
  3. 混合数组中的额外数字
  4. 如果第一个参数不是[],请返回Array

const uniqBy = (arr, predicate) => {
  if (!Array.isArray(arr)) { return []; }

  const cb = typeof predicate === 'function' ? predicate : (o) => o[predicate];

  const pickedObjects = arr
    .filter(item => item)
    .reduce((map, item) => {
        const key = cb(item);

        if (!key) { return map; }

        return map.has(key) ? map : map.set(key, item);
    }, new Map())
    .values();
 
  return [...pickedObjects];
};

const a = [ 
  12,
  undefined,
  { id: 1, name: 'bob' },
  null,
  { id: 1, name: 'bill' },
  null,
  undefined
];

const b = [ 
  12,
  { id: 1, name: 'bob' },
  { id: 1, name: 'bill' },
];

uniqBy(a, 'name');
uniqBy(b, Math.floor);
uniqBy([2.1, 1.2, 2.3], Math.floor);

答案 3 :(得分:0)

您可以使用按名称排序的排序和基于邻域比较的过滤器,如下所示:

var sourceArray = [ { id: 1, name: 'bob' },
  { id: 1, name: 'bill' },
  { id: 1, name: 'bill' } ,
  {id: 2,name: 'silly'},
  {id: 2,name: 'billy'}]

var uniqBy = (inputArray, callback) => inputArray.sort((a,b) => callback(a) > callback(b))
.filter((x,i,arr) => i === arr.length -1 ? true : callback(x) !== callback(arr[i+1]));
var inputFunc = item => item.name;


var destArray = uniqBy(sourceArray, inputFunc)
console.log('destArray', destArray)