投影JavaScript对象字段的最佳方法是什么?

时间:2018-03-15 06:06:12

标签: javascript optimization ecmascript-6 ecmascript-5

我必须将一些javascript字段投射到新对象。

例如我有一个下面的对象

import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;

import com.stagap.stagap.R;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import static android.os.Environment.getExternalStoragePublicDirectory;

public class GalleryActivity extends AppCompatActivity {

    private Toolbar galleryToolbar;
    private RecyclerView recyclerGallery;
    private ArrayList<File> imageFiles;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gallery);
        galleryToolbar = findViewById(R.id.galleryToolbar);
        setSupportActionBar(galleryToolbar);
        recyclerGallery = findViewById(R.id.recyclerGallery);

        GridLayoutManager gridLayoutManager = new GridLayoutManager(getBaseContext(), 3);
        recyclerGallery.setLayoutManager(gridLayoutManager);
        imageFiles = new ArrayList<>();

        readImages(getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), imageFiles);
//        if(isExternalStorageAvailable() && !isExternalStorageReadOnly())
//            readImages(Environment.getExternalStorageDirectory(), imageFiles);
        Collections.sort(imageFiles, new SortFolder());

        GalleryRecyclerAdapter adapter = new GalleryRecyclerAdapter(getBaseContext(), imageFiles);
        recyclerGallery.setAdapter(adapter);
        recyclerGallery.setHasFixedSize(true);


    }

    private void readImages(File root ,ArrayList<File> imageList) {

        File[] files = root.listFiles();
        for(File file: files){

            if(file.isDirectory()){
                readImages(file, imageList);
            }else{
                if(file.getName().endsWith(".png") ||
                        file.getName().endsWith(".jpeg") ||
                        file.getName().endsWith(".jpg")){
                        imageList.add(file);
                }
            }
        }
    }

    class SortFolder implements Comparator<File> {
        @Override
        public int compare(File f1, File f2) {
            if (f1.lastModified() > (f2.lastModified())) {
                return -1;
            } else if (f1.lastModified() < (f2.lastModified())) {
                return +1;
            } else {
                return 0;
            }
        }
    }

    private static boolean isExternalStorageAvailable() {
        String extStorageState = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(extStorageState)) {
            return true;
        }
        return false;
    }

    private static boolean isExternalStorageReadOnly() {
        String extStorageState = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState)) {
            return true;
        }
        return false;
    }
}

我想要包含var obj = { fn : 'Abc', ln : 'Xyz', id : 123, nt : 'Note', sl : 50000}

的新对象
fn and id

基于投影

var projectedObj = { fn : 'Abc', id : 123 }

类似这样的事情

var projection = { fn : 1, id : 1 }

这样做的最佳方式或优化方法是什么。

5 个答案:

答案 0 :(得分:2)

只需循环投影对象并获得投射的关键点。例如,

function project(obj, projection) {
    let projectedObj = {}
    for(let key in projection) {
        projectedObj[key] = obj[key];
    }
    return projectedObj;
}

答案 1 :(得分:2)

您可以使用array#reduce并迭代投影对象的所有键,并根据键提取原始对象的值并创建新对象。

var project = (o, p) => {
  return Object.keys(p).reduce((r,k) => {
    r[k] = o[k] || '';
    return r;
  },{});
}

var obj = { fn : 'Abc', ln : 'Xyz', id : 123,  nt : 'Note', sl : 50000};
var projection = { fn : 1, id : 1 };
var projectedObj = project(obj, projection);
console.log(projectedObj);

您还可以array#mapObject#assign一起使用来创建新对象。

var project = (o, p) => {
  return Object.assign(...Object.keys(p).map(k => ({[k]: o[k]})));
}

var obj = { fn : 'Abc', ln : 'Xyz', id : 123,  nt : 'Note', sl : 50000};
var projection = { fn : 1, id : 1 };
var projectedObj = project(obj, projection);
console.log(projectedObj);

答案 2 :(得分:0)

您可以reduceprojection个键返回obj值作为:

&#13;
&#13;
var obj = { fn : 'Abc', ln : 'Xyz', id : 123, nt : 'Note', sl : 50000}
var projection = { fn : 1, id : 1 }

function project(obj, projection) {
  return Object.keys(projection).reduce((a, e) => { a[e] = obj[e]; return a; }, {});
}

console.log(project(obj, projection));
&#13;
&#13;
&#13;

答案 3 :(得分:0)

我是这样做的。它可以处理嵌套对象,但可能无法处理可以是值或对象的属性。

let entity = {
    timeStamp: "1970-01-01T00:00:00.000Z",
    value: 1,
    itemList: [
        {
            amount: 1,
            product: {
                name: "Product 0",
                _links: { self: { href: "https://example.com:8080/api/entityA/1" } }
            },
            value: 1,
            flag: false,
            _links: { self: { href: "https://example.com:8080/api/entityB/1" } }
        }
    ],
    summerTime: false,
    parent: {
        grandParentA: {
            name: "Grand Parent 0",
            _links: { self: { href: "https://example.com:8080/api/entityC/1" } }
        },
        grandParentB: null,
        name: "Parent 0",
        _links: { self: { href: "https://example.com:8080/api/entityD/1" } }
    },
    _links: { self: { href: "https://example.com:8080/api/entityE/1" } }
};

let entityProjection = {
    parent: {
        grandParentA: {
            _links: { self: { href: false } }
        },
        grandParentB: {
            _links: { self: { href: false } }
        },
        _links: { self: { href: false } }
    },
    _links: { self: { href: false } }
}

const project = (object, projection) => {
    return Object.keys(projection).reduce((a, e) => ({ ...a, [e]: object[e] ? (projection[e] ? project(object[e], projection[e]) : object[e]) : object[e] }), {});
}

console.log(project(entity, entityProjection));

答案 4 :(得分:0)

作为一种不传递投影对象,而是列出要投影为逗号分隔的字符串的属性的替代方法,此模块可以做到这一点。请注意,此模块不支持对象,但支持数组。

    var linqmodule = (function() {
  projection = function(members) {
    var membersArray = members.replace(/s/g, "").split(",");
    var projectedObj = {};

    for (var i = 0; i < this.length; i++) {
      for (var j = 0; j < membersArray.length; j++) {
        var key = membersArray[j];
        if (j === 0) {
          projectedObj[i] = {};
        }
        projectedObj[i][key] = this[i][key];
      }
    }

    return projectedObj;
  };
  Array.prototype.select = projection;

  dumpmethod = function(arrayobj) {
    var result = "";
    result += "[";

    for (var i = 0; i < Object.keys(arrayobj).length; i++) {
      var membersArray = Object.keys(arrayobj[i]);
      for (var j = 0; j < membersArray.length; j++) {
        if (j === 0) {
          result += "{";
        }
        var key = membersArray[j];
        result +=
          "key: " +
          key +
          " , value: " +
          arrayobj[i][key] +
          (j < membersArray.length - 1 ? " , " : "");
        if (j === membersArray.length - 1) {
          result +=
            "}" + (i < Object.keys(arrayobj).length - 1 ? "," : "") + "\n";
        }
      }
    }
    result += "]";

    return result;
  };

  return {
    dump: dumpmethod
  };
})();

要投影您的Json对象数组,您可以使用以下示例作为指导:

var someCountries = [
          { country: "Norway", population: 5.2, code: "NO" },
          { country: "Finland", population: 5.5, code: "SU" },
          { country: "Iceland", population: 0.4, code: "IC" },
          { country: "Sweden", population: 10.2, code: "SW" }
        ];
var result = someNums.select("country,population");
console.log(linqmodule.dump(result));

然后,结果数组将包含投影结果(并复制到新数组中)而没有字段“代码”。

这并没有回答问题,因为它询问了单个对象和投影对象,但是它显示了如何使用对象数组(在数组的每个对象中具有相同的字段)实现相同的目的。如此众多的人会发现它对于类似的情况很有用。